Jenkins Pipeline语法
<p><img src="https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20220419081406065.png" alt="im
目录
[TOC]
1、初识Pipeline核心语法
1.什么是Pipeline
stage:流水线中的每一个阶段;
agent:流水线的运行节点;
jenkinsfile :以代码的方式描述流水线;Jenkins在运行Pipeline任务的时候会按照Jenkinsfile中定义的代码顺序执行;
2.创建Pipeline作业
🍀 作业的项目类型
1.自由风格(图形化界面)被淘汰!
2.Pipeline (代码)
注意:
jenkinsfile解决的难点、通点是:一次改变,随处可用,便于流水线的管理和维护!
自由风格:全部都要在图形化界面上进行配置的。
Pipeline:以代码方式定义流水线。
使用场景:
例如目前有250个流水线项目,如果都是自由风格类型,现在有个需求,想对这所有的项目统一配置一个参数,该如何做呢?
1、自由风格类型(1.手动傻瓜式一个个项目做哈哈 2.如果可以,可调用api进行配置)
2、流水线类型 (直接修改jenkinsfile即可实现,一次改变,随处可用效果!)
学习完pipeline之后,你可以基于公司现有的流水线进行一些改造!
🍀 要想使用这个Pipeline作业类型首先要安装Pipeline插件
🍀 创建Pipeline作业方法
day2-pipeline-demo
全局的一些选项:
构建触发器:
流水线:
第一种方式:Pipeline script
第二种方式:Pipeline script from SCM
3.运行第一条Pipeline
🍀 亲自测试
一个pipeline流水线无非就是如下几个动作 1、创建一个Pipeline流水线项目 2、编写Jenkinsfile文件 3、触发构建 4、调试
这里选择一个Hello World测试案例,点击保存:
构建:
验证:
一个简单的demo测试结束。😘
4.调试-Pipeline-回放
🍀 亲自测试
这里修改下上一次构建过的jenkinsfile代码:
测试结束。
🍀 注意:如果某次的构建失败了的话,那么本次回放是不可用的,即上次的代码会丢失!(注意:推荐在本地编辑器编辑代码,然后复制到回放中就好)
5.什么是Jenkinsfile
1、Jenkinsfile-顶级块-pipeline{}
2、Jenkinsfile-二级块-agent{}
3、Jenkinsfile-二级块-options{}
也就是如下的配置:
4、Jenkinsfile-二级块-stages{}
:warning: 注意
- Jenkinsfile支持
声明式
和命令式
2种方式来写代码,一般推荐使用声明式。- 如果把命令式代码写在了steps里面,有的命令会报错的,因此一般要写在
scriptP{}
里面;- 这样一来的话,Jenkinsfile就由声明式代码,内嵌一部分命令式代码组成,更加增加了其灵活性;
5、Jenkinsfile-二级块-post{}
示例
- 案例代码如下
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
script{
println("获取代码")
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
- 将案例代码拷贝到流水线里,然后保存,立即构建即可:
可以运行成功,但是有个问题:
- 我们再来使用
Blue Ocean
观察下现象:
测试结束。😘
2、Pipeline开发工具
1.片段生成器
🍀 亲自测试
- 这里随便打开一个项目,点击
流水线语法
,点击片段生成器
:
- 这里来测试下,我们先来使用下
echo: Print Message
测试下
将生成的代码拷贝到源代码文件里:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
echo 'i love you ,xyy'
script{
println("获取代码")
echo 'i love you ,xyy'
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
此时,有个问题:我将这个echo 'i love you ,xyy'
语句分别写在steps和script里,那么等会构建下,是否会报错呢?
在上次构建地方,点击回放,将新代码拷贝进去,点击运行
,观察效果:
可以看到,会正常构建的:
- 此时,我们再选择
sh: Shell Script
,生成流水线脚本
此时,有个问题:我将这个sh 'ehco "i love you, hurt"''
语句分别写在steps和script里,那么等会构建下,是否会报错呢?
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
echo 'i love you ,xyy'
sh 'echo "i love you,hurt"'
script{
println("获取代码")
echo 'i love you ,xyy'
sh 'echo "i love you,hurt"'
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
在上次构建地方,点击回放,将新代码拷贝进去,点击运行
,观察效果:
可以看到,shell命令放在stage里也是不会报错的。
🍀 总结
虽然有的shell命令放在stage里也不会报错的,但是为了代码的规范性及可读性,强烈建议将shell命令都放在script里!(有可能if else放在stage里可能会报错)
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
script{
println("获取代码")
echo 'i love you ,xyy'
sh 'echo "i love you,hurt"'
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
2.声明式语法生成器
🍀 示例
可以看到有很多Sample Directive:
例如这里可以选择agent: Agent
3.全局变量参考
🍀 示例
env是全局变量的:
- 全局变量使用测试
我们来使用下BUILD_ID
这个全局变量下:
:warning: 注意:这里一定要使用双引号,否则会把其当做字符串打印出的!(linux中单引号与双引号的区别)
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
script{
println("获取代码")
echo 'i love you ,xyy'
echo "${BUILD_ID}"
echo "${env.BUILD_ID}"
echo "$BUILD_ID"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
可以看到会构建成功:
🍀 创建全局变量并测试
我们首先将全局变量的定义放在stage
里面:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
env.myName = "xyy"
script{
println("获取代码")
echo 'i love you ,xyy'
echo "${BUILD_ID}"
echo "${env.BUILD_ID}"
echo "$BUILD_ID"
echo "${myName}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
结果构建失败了:
此时,我们修改下代码,再把其放在script里面,看能否构建成功:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
script{
env.myName = "xyy"
echo "${myName}"
println("获取代码")
echo 'i love you ,xyy'
echo "${BUILD_ID}"
echo "${env.BUILD_ID}"
echo "$BUILD_ID"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
可以看到,本次构建成功,原来就是把命令式代码写在stage位置了,导致构建失败!因此也验证了上面的结论脚本式的语法我们都写在script里面
。
- 此时,有个问题:
刚才在检出代码阶段定义的全局变量,是否可以在构建阶段里面使用?这边来测试下
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
script{
env.myName = "xyy"
echo "${myName}"
env.branchName = "dev"
println("获取代码")
echo 'i love you ,xyy'
echo "${BUILD_ID}"
echo "${env.BUILD_ID}"
echo "$BUILD_ID"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
结论:可以看到,在某一个stage里定义的全局变量,在其他stage里也是可以使用的!
🍀 示例:如何使用命令式语法来定义局部变量
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
//管道运行选项
options {
skipStagesAfterUnstable()
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
script{
envType = "test"
echo "envType: ${envType}"
env.myName = "xyy"
echo "${myName}"
env.branchName = "dev"
println("获取代码")
echo 'i love you ,xyy'
echo "${BUILD_ID}"
echo "${env.BUILD_ID}"
echo "$BUILD_ID"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
echo "envType: ${envType}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
进行构建:
结论:发现在script里定义的局部变量,在其他stage里也是可以使用的。。。😥并且,也是可以在stage里引用局部变量的,也是不会报错的。
3、深入Pipeline核心语法
1.agent{}流水线运行节点
🍀 注意
none情况:适合于流水线的阶段分布在不同的agent上运行;
还是指定节点这种方式用的多一些;
2.stages{}流水线阶段
3.post{}
🍀 注意
- always:例如每次执行后清理缓存动作;
- success:执行成功后,也可触发下一动作,例如触发CD;(远程构建)
- failure/aborted:可能要给开发人员发个邮件。
4.enironment{}环境变量
推荐:声明式语法里使用enironment这个语句块来写。
🍀 示例:全局变量测试
编写代码:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
environment{
branchName = "dev"
version = "1.1.1"
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
steps{
script{
echo "${branchName}"
echo "${version}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
echo "${version}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
立即构建:构建成功。
🍀 示例:局部变量测试
编写如下代码:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
environment{
branchName = "dev"
version = "1.1.1"
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
environment{
branchName = "test"
}
steps{
script{
echo "${branchName}"
echo "${version}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
echo "${version}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
运行:
注意:这里涉及到一个作用域问题,局部变量优先级高于全局变量。
5.options{}流水线运行时选项
🍀 注意:以上不用硬记的,需要用到时可以到声明式语法生成器
那里寻找就好
6.parameters{}参数化构建
🍀 示例:定义字符串参数和选项参数
在声明式语法生成器
里选择参数构建-字符串构建:
代码如下:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
environment{
branchName = "dev"
version = "1.1.1"
}
parameters {
string defaultValue: '1.1.2', description: '版本号', name: 'VERSION', trim: true
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
environment{
branchName = "test"
}
steps{
script{
echo "${branchName}"
echo "${version}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
echo "${version}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
进行构建:
在配置这里也是可以看到参数化构建
的选项的:
- 我们再来定义下选项参数:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
environment{
branchName = "dev"
version = "1.1.1"
}
parameters {
string defaultValue: '1.1.2', description: '版本号', name: 'VERSION', trim: true
choice choices: ['prod', 'test', 'dev'], name: 'envType'
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
environment{
branchName = "test"
}
steps{
script{
echo "${branchName}"
echo "${version}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
echo "${version}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
构建:
- 参数定义好了,该如何引用呢?
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
environment{
branchName = "dev"
version = "1.1.1"
}
parameters {
string defaultValue: '1.1.2', description: '版本号', name: 'VERSION', trim: true
choice choices: ['prod', 'test', 'dev'], name: 'envType'
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
// environment{
// branchName = "test"
// }
steps{
script{
echo "${branchName}"
echo "${version}"
echo "${VERSION}"
echo "${env.VERSION}"
echo "${params.VERSION}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
echo "${version}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
构建:
- 我们再来测试下如下现象:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
environment{
branchName = "dev"
// version = "1.1.1"
}
parameters {
string defaultValue: '1.1.2', description: '版本号', name: 'VERSION', trim: true
choice choices: ['prod', 'test', 'dev'], name: 'envType'
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
// environment{
// branchName = "test"
// }
steps{
script{
echo "${branchName}"
// echo "${version}"
echo "${VERSION}"
echo "${env.VERSION}"
echo "${params.VERSION}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
// echo "${version}"
}
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
构建:
结论:
如果同时有
environment
和parameters
时,env.VERSION
和VERSION
默认会使用enironment的值的,因此要想使用parameters,推荐使用params.VERSION
来引用。这里需要注意下,大小写变量问题。
7.triggers{}触发器
🍀 注意
定时构建:例如代码扫描。
SCM轮询构建:之前自由风格类型用的多,现在pipeline用的不多了,后面会讲一个更高级的工具。(xx webhook)
8.input{}触发器
🍀 示例
生成代码:
编写代码:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
// triggers {
// cron 'H 11 * * *'
// }
environment{
branchName = "dev"
// version = "1.1.1"
}
parameters {
string defaultValue: '1.1.2', description: '版本号', name: 'VERSION', trim: true
choice choices: ['prod', 'test', 'dev'], name: 'envType'
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
// environment{
// branchName = "test"
// }
steps{
script{
echo "${branchName}"
// echo "${version}"
echo "${VERSION}"
echo "${env.VERSION}"
echo "${params.VERSION}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
// echo "${version}"
}
}
}
stage("deploy"){
input {
message '选择开发环境'
ok '提交'
parameters {
choice choices: ['dev', 'prod', 'test'], name: 'envName'
}
}
steps{
echo "deploy ${envName}"
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
构建:
以BlueOcean方式打开构建过程:
🍀 注意
9.when{}阶段运行控制
🍀 示例
编写代码:
pipeline{
//指定运行此流水线的节点
agent { node { label "build"}}
// triggers {
// cron 'H 11 * * *'
// }
environment{
branchName = "dev"
// version = "1.1.1"
}
parameters {
string defaultValue: '1.1.2', description: '版本号', name: 'VERSION', trim: true
choice choices: ['prod', 'test', 'dev'], name: 'envType'
}
//流水线的阶段
stages{
//阶段1 获取代码
stage("CheckOut"){
// environment{
// branchName = "test"
// }
steps{
script{
echo "${branchName}"
// echo "${version}"
echo "${VERSION}"
echo "${env.VERSION}"
echo "${params.VERSION}"
}
}
}
stage("Build"){
steps{
script{
println("运行构建")
echo "${branchName}"
// echo "${version}"
}
}
}
stage("deploy"){
when{
environment name: "branchName", value: "dev"
}
input {
message '选择开发环境'
ok '提交'
parameters {
choice choices: ['dev', 'prod', 'test'], name: 'envName'
}
}
steps{
echo "deploy ${envName}"
}
}
}
post {
always{
script{
println("流水线结束后,经常做的事情")
}
}
success{
script{
println("流水线成功后,要做的事情")
}
}
failure{
script{
println("流水线失败后,要做的事情")
}
}
aborted{
script{
println("流水线取消后,要做的事情")
}
}
}
}
这里的自己现象:自己现象为什么和老师的不一样呢。。。😥
老师现象:
10.parallel{}阶段并行
🍀 示例
我们先来给master节点打个master
标签:
编写代码:
pipeline {
agent any
stages {
stage('Parallel Stage') {
failFast true
parallel {
stage('windows') {
agent {
label "master"
}
steps {
echo "windows"
}
}
stage('linux') {
agent {
label "build"
}
steps {
echo "linux"
}
}
}
}
}
}
构建:
关于我
我的博客主旨:我希望每一个人拿着我的博客都可以做出实验现象,先把实验做出来,然后再结合理论知识更深层次去理解技术点,这样学习起来才有乐趣和动力。并且,我的博客内容步骤是很完整的,也分享源码和实验用到的软件,希望能和大家一起共同进步!
各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人免费帮您解决问题:
个人微信二维码:x2675263825 (舍得), qq:2675263825。
个人微信公众号:云原生架构师实战
个人博客地址:www.onlyonexl.cn
个人csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
个人已开源干货😘
不服来怼:宇宙中最好用的云笔记 & 其他开源干货:https://www.yuque.com/go/doc/73723298?#
最后
好了,关于Jenkins Pipeline语法就到这里了,感谢大家阅读,最后贴上我女神的photo,祝大家生活快乐,每天都过的有意义哦,我们下期见!
更多推荐
所有评论(0)