一、pipeline语法介绍
Jenkins Pipeline 是一种插件,它允许你以代码的方式定义持续集成和持续交付(CI/CD)流程。它基于 Jenkins 的 Groovy DSL(领域特定语言),提供了一种强大的方式来描述和自动化构建、测试和
部署软件。
DSL 是什么?
DSL 其实是 Domain Specific Language 的缩写,中文翻译为领域特定语言(下简称 DSL);而
与 DSL 相对的就是 GPL,这里的 GPL 并不是我们知道的开源许可证,而是 General Purpose
Language 的简称,即通用编程语言,也就是我们非常熟悉的 Objective-C、Java、Python 以及
C 语言等等。
Pipeline 脚本可以被定义在 Jenkins 的界面中,也可以作为一个 Jenkinsfile 文件存在于代码仓库 中,以使流程定义与代码版本控制一起管理。以下是 Jenkins Pipeline 的基本概述:
1、阶段(Stages): Pipeline 由一个或多个阶段组成。每个阶段代表一个任务,例如构建、测试、 部署等。阶段通常按照顺序执行,可以并行执行或顺序执行。
2、步骤(Steps): 每个阶段包含一个或多个步骤。步骤是具体的操作,例如构建代码、运行测试、 推送到远程服务器等。Jenkins 提供了一系列内置步骤来完成常见的构建和部署任务,同时还可以使用自 定义步骤。3、代理(Agent): 代理定义了执行阶段的运行环境。它可以是 Jenkins 主节点(master)或一 个或多个远程节点(agent)。你可以指定阶段在特定的代理上执行,这使得你可以根据需要进行分布式 构建。
4、变量(Variables): 变量允许你在 Pipeline 中存储和操作数据。你可以定义全局变量,也可以 在阶段或步骤级别定义局部变量。变量可以用于保存构建号、版本号、环境配置等信息。
5、控制流(Control Flow): Pipeline 提供了条件、循环和错误处理等控制流语句,允许你根据不 同的条件执行不同的操作或重试失败的步骤。
结构示例
pipeline {
agent any
stages {
steps {
sh 'mvn clean package'
}
}
steps {
sh 'mvn test'
}
}
steps {
sh 'mvn deploy'
}
}
}
}
释意
二、Jenkins pipeline入门
Pipeline 脚本是用 Groovy 语言编写的,但不需要专门学习 Groovy。Groovy 是一种基于 JVM 的敏捷开发语言,它结合了 Python、Ruby 和 Smalltalk 的特性,并且可以与 Java 代码很好地结合,也可以使用其他非 Java 语言编写的库。
Pipeline 支持两种语法:声明式和脚本式。
声明式语法是 Pipeline 的主要语法,它包括以下核心流程:
1、pipeline: 声明 Pipeline 脚本的起始点,表明内容为声明式的 Pipeline 脚本。
2、agent: 指定 Pipeline 运行的节点(可以是 slave 或 master 节点)。
3、stages: 包含所有阶段的集合,例如打包、部署等。
4、stage: 定义一个阶段,可以有多个阶段。
5、steps: 定义每个阶段的最小执行单元。
6、post: 定义构建后的操作,根据构建结果执行相应的操作。
示例
pipeline {
agent any
stages {
steps {
echo "I am liangxi"
}
}
}
post {
always {
echo "The process is ending"
}
}
}
在这个示例中:
可选项
1.Environment
environment 指令用于指定一系列键值对,这些键值对将作为环境变量定义在 Pipeline 的所有步骤或特定阶段的步骤中。具体取决于 environment 指令在 Pipeline 中的位置。
示例
pipeline {
agent any
environment {
//设置环境变量
CC = 'clang'
}
stages {
stage('Example') {
steps {
//执行printenv命令查看所有的环境变量
sh 'printenv'
}
}
}
}
日志输出
Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/test
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Example)
[Pipeline] sh
+ printenv
JENKINS_HOME=/var/jenkins_home
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimental
CI=true
RUN_CHANGES_DISPLAY_URL=http://192.168.1.100:30002/job/test/1/display/redirect?page=changes
HOSTNAME=jenkins-849b5d5784-7wndc
SHLVL=0
NODE_LABELS=built-in
HUDSON_URL=http://192.168.1.100:30002/
HOME=/var/jenkins_home
BUILD_URL=http://192.168.1.100:30002/job/test/1/
HUDSON_COOKIE=a7486a9f-f1a2-48a4-b7d5-99019f9e7028
JENKINS_SERVER_COOKIE=durable-7190c2fadc48570bd1d6b9ff3df70884d6b72f619c1a447143f9aae059f70e9f
JENKINS_UC=https://updates.jenkins.io
WORKSPACE=/var/jenkins_home/workspace/test
REF=/usr/share/jenkins/ref
NODE_NAME=built-in
RUN_ARTIFACTS_DISPLAY_URL=http://192.168.1.100:30002/job/test/1/display/redirect?page=artifacts
STAGE_NAME=Example
EXECUTOR_NUMBER=1
JENKINS_SERVICE_PORT_50000_TCP_ADDR=10.100.103.249
RUN_TESTS_DISPLAY_URL=http://192.168.1.100:30002/job/test/1/display/redirect?page=tests
BUILD_DISPLAY_NAME=#1
JENKINS_VERSION=2.421
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
JENKINS_INCREMENTALS_REPO_MIRROR=https://repo.jenkins-ci.org/incrementals
HUDSON_HOME=/var/jenkins_home
JOB_BASE_NAME=test
PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JENKINS_SERVICE_PORT_8080_TCP_ADDR=10.100.103.249
JENKINS_SERVICE_SERVICE_HOST=10.100.103.249
JENKINS_SERVICE_PORT_50000_TCP_PORT=50000
BUILD_ID=1
JENKINS_SERVICE_SERVICE_PORT_AGENT=50000
KUBERNETES_PORT_443_TCP_PORT=443
BUILD_TAG=jenkins-test-1
JENKINS_SERVICE_PORT_50000_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PROTO=tcp
JENKINS_URL=http://192.168.1.100:30002/
JENKINS_SERVICE_PORT_8080_TCP_PORT=8080
LANG=C.UTF-8
JOB_URL=http://192.168.1.100:30002/job/test/
JENKINS_SERVICE_PORT_8080_TCP_PROTO=tcp
BUILD_NUMBER=1
JENKINS_NODE_COOKIE=ba947609-37ee-4863-869a-a0a0e83db1ff
RUN_DISPLAY_URL=http://192.168.1.100:30002/job/test/1/display/redirect
JENKINS_SERVICE_SERVICE_PORT=8080
JENKINS_SERVICE_PORT=tcp://10.100.103.249:8080
JENKINS_SLAVE_AGENT_PORT=50000
HUDSON_SERVER_COOKIE=154a81c36d26db76
JOB_DISPLAY_URL=http://192.168.1.100:30002/job/test/display/redirect
JENKINS_SERVICE_PORT_50000_TCP=tcp://10.100.103.249:50000
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
JOB_NAME=test
COPY_REFERENCE_FILE_LOG=/var/jenkins_home/copy_reference_file.log
PWD=/var/jenkins_home/workspace/test
JENKINS_SERVICE_PORT_8080_TCP=tcp://10.100.103.249:8080
JENKINS_SERVICE_SERVICE_PORT_WEB=8080
JAVA_HOME=/opt/java/openjdk
KUBERNETES_SERVICE_HOST=10.96.0.1
WORKSPACE_TMP=/var/jenkins_home/workspace/test@tmp
设置的环境变量
CC=clang
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
2.Options
options 指令用于设置 Pipeline 的行为,包括构建丢弃、并发执行、代码检出、超时、重试和时间戳等选项。
备注:
1、什么叫做代码检出?
在 Jenkins Pipeline 中,代码检出是指从源代码版本控制系统(如 Git、Subversion 等)获取代码并将其放置到 Jenkins 代理节点上供后续构建步骤使用的过程。通常,在 Pipeline 的每个阶段之前,Jenkins 会自动执行默认的代码检出步骤,以确保在每个构建阶段开始之前,代码都是最新的。这样可以确保每个阶段都在相同的代码基础上运行。
然而,有时候可能希望跳过默认的代码检出步骤,而是手动控制代码的获取。这在以下情况下可能有用:
1)如果 Pipeline 中的某个阶段不需要访问代码库,例如只是执行一些不依赖于代码的操作。
2)如果希望在 Pipeline 的某个特定阶段之前执行自定义的代码检出逻辑,例如从其他来源获取代码或切换到不同的代码分支。当使用 options { skipDefaultCheckout() }时,Pipeline 将跳过默认的代码检出步骤。这意味着在 Pipeline 的任何阶段中,需要自行编写代码检出逻辑,以便获取代码并将其放置在适当的位置供后续步骤使用。这样可以完全控制代码的获取方式和时机。
请注意,如果使用了 skipDefaultCheckout(),则在 Pipeline 的任何阶段中,都需要显式地编写代码检出的步骤,否则可能会导致后续步骤无法正常执行,因为它们无法访问到代码。
可用选项
disableConcurrentBuilds:禁止并发执行 Pipeline,用于防止同时访问共享资源等场景。
示例:options { disableConcurrentBuilds() }
buildDiscarder:设置 Pipeline 保留的构建数量。可以使用 logRotator 插件配置日志轮换,指定要保留的最大构建数量。
示例:options { buildDiscarder(logRotator(numToKeepStr: '1')) }
skipDefaultCheckout:跳过默认设置的代码检出步骤。
示例:options { skipDefaultCheckout() }:
skipStagesAfterUnstable:一旦构建状态进入"Unstable"状态,就跳过之后的所有 stage。
示例:options { skipStagesAfterUnstable() }:
在 Jenkins 中,构建状态表示构建过程中的结果状态,常见的状态有"成功"(Success)、"失败"(Failure)和"不稳定"(Unstable)。"Unstable"状态表示构建完成,但存在一些非关键性的问题或警告。使用 options { skipStagesAfterUnstable() }配置后,当 Pipeline 的某个阶段将构建状态设置为"Unstable"时,Jenkins 将立即跳过该阶段之后的所有阶段,直接进入 Pipeline 的结束状态。这样可以提高构建过程的效率,避免在已知构建不稳定的情况下继续执行后续阶段。
例如,假设有一个 Pipeline 包含三个阶段(stage):A、B 和 C。如果在阶段 B 中设置了一个条件,当某些非关键测试失败时将构建状态设置为"Unstable",那么使用 options { skipStagesAfterUnstable() }后,如果阶段 B 的构建状态为"Unstable",Jenkins 将跳过阶段 C,并直接结束 Pipeline 的执行。
timeout:设置 Pipeline 运行的超时时间,超过超时时间,作业会被自动终止。可以指定时间和单位。
示例:options { timeout(time: 1, unit: 'HOURS') }
retry:在失败后,重试整个 Pipeline 的次数。可以指定重试次数。
示例:options
{ retry(3) }
timestamps:在 Pipeline 生成的所有控制台输出中预定义时间戳。
示例:options { timestamps() }:
当你在 Pipeline 中执行一系列的步骤和命令时,Jenkins 会在控制台输出中显示每个步骤的执行结果和日志信息。这些输出通常以文本形式显示,其中每行代表一个输出条目。
通过使用 options { timestamps() }配置,Jenkins 会在每个控制台输出的行前添加一个时间戳,以显示该行输出的时间。这样可以帮助你更好地追踪和分析 Pipeline 的执行过程,特别是在需要查找特定输出或分析日志的时间相关性时。
示例
pipeline {
agent any
options{
timestamps()
}
stages {
steps {
echo 'liangxi'
}
}
}
}
日志输出
Started by user admin
Running on Jenkins in /var/jenkins_home/workspace/test
07:43:16 liangxi
Finished: SUCCESS
3.parameters
parameters 指令用于在 Jenkins Pipeline 中定义参数列表,这些参数允许用户在触发 Pipeline 时提供不同的值。参数值可以通过 params 对象在 Pipeline 的各个阶段中访问和使用。parameters 指令应该位于 Pipeline 的最外层,并且只能在 Pipeline 中出现一次。它定义了在触发 Pipeline 时用户可以提供的参数列表。参数定义的作用域是全局的,可以在整个 Pipeline 中使用。
1、string 参数类型:用于定义字符串类型的参数。可以指定参数的名称、默认值和描述。
例如:string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '')
2、booleanParam 参数类型:用于定义布尔类型的参数。您可以指定参数的名称、默认值和描述。
例如:booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '')
示例
pipeline{
agent any
parameters{
string(name:'name',defaultValue:'liangxi',description:'"What is your name?"')
booleanParam(name:'liangxi',defaultValue:true,description:'This is my name')
}
stages{
stage("stage1"){
steps{
echo "$name"
echo "$liangxi"
}
}
}
}
构建
第一次:
Started by user admin
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/parameters
[Pipeline] {
[Pipeline] stage
[Pipeline] { (stage1)
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
//报错没有这样的属性或类
Also: org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: 455f3d00-5cdd-4aef-944f-432240771acc
groovy.lang.MissingPropertyException: No such property: name for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:285)
at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:375)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:379)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:355)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:355)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
at org.jenkinsci.plugins.workflow.cps.LoggingInvoker.getProperty(LoggingInvoker.java:121)
at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
at WorkflowScript.run(WorkflowScript:10)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.delegateAndExecute(ModelInterpreter.groovy:137)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.executeSingleStage(ModelInterpreter.groovy:666)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.catchRequiredContextForNode(ModelInterpreter.groovy:395)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.catchRequiredContextForNode(ModelInterpreter.groovy:393)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.executeSingleStage(ModelInterpreter.groovy:665)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:288)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.toolsBlock(ModelInterpreter.groovy:544)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.toolsBlock(ModelInterpreter.groovy:543)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:276)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withEnvBlock(ModelInterpreter.groovy:443)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withEnvBlock(ModelInterpreter.groovy:442)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:275)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withCredentialsBlock(ModelInterpreter.groovy:481)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withCredentialsBlock(ModelInterpreter.groovy:480)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:274)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.inDeclarativeAgent(ModelInterpreter.groovy:586)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.inDeclarativeAgent(ModelInterpreter.groovy:585)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:272)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.stageInput(ModelInterpreter.groovy:356)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.stageInput(ModelInterpreter.groovy:355)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:261)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.inWrappers(ModelInterpreter.groovy:618)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.inWrappers(ModelInterpreter.groovy:617)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:259)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withEnvBlock(ModelInterpreter.groovy:443)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.withEnvBlock(ModelInterpreter.groovy:442)
at org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter.evaluateStage(ModelInterpreter.groovy:254)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:73)
at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:65)
at jdk.internal.reflect.GeneratedMethodAccessor358.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:152)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:146)
at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:136)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:275)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:146)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:187)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:423)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:331)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:295)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:97)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:139)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
at jenkins.util.ErrorLoggingExecutorService.lambda$wrap$0(ErrorLoggingExecutorService.java:51)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Finished: FAILURE
第二次构建
日志输出
Started by user admin
[
[
Running on Jenkins in /var/jenkins_home/workspace/parameters
[
[
[
[
liangxi
[
true
[
[
[
[
[
Finished: SUCCESS
第三次自定义
日志输出
Started by user admin
[
[
Running on Jenkins in /var/jenkins_home/workspace/parameters
[
[
[
[
你好
[
false
[
[
[
[
[
Finished: SUCCESS
4.Triggers
triggers 指令定义了 Pipeline 自动化触发的方式。目前有三个可用的触发器:cron 和 pollSCM 和upstream
作用域:被pipeline包裹,在符合条件下自动触发pipeline
1、cron:
接受一个 cron 风格的字符串来定义 Pipeline 触发的时间间隔,例如:
triggers { cron('H 4/* 0 0 1-5') }
cron 表达式的各个字段:
H:代表 Hashed 值,用于避免多个任务同时触发。在每个小时内,相同的 H 值只会触发一个任
务。这可以确保任务在指定的时间范围内只执行一次。
4/*:表示分钟字段,指定每小时的第 4 分钟。
0:表示小时字段,指定小时为 0 点。
0:表示天字段,指定日期为任意日期。
1-5:表示工作日字段,指定工作日为周一到周五。
综上所述,该 cron 触发器的定义规则意味着在每个工作日的凌晨 0 点 4 分触发 Pipeline 的执
行。
这意味着 Pipeline 会在工作日的每个早晨 0 点 4 分执行一次。
5.input
stage 的 input 指令允许你使用 input step 提示输入。 在应用了 options 后,进入 stage 的agent 或评估 when 条件前,stage 将暂停。 如果 input 被批准, stage 将会继续。 作为 input 提交的一部分的任何参数都将在环境中用于其他 stage
配置项
message
id
input 的可选标识符, 默认为 stage 名称。
ok
submitter
submitterParameter
parameters
提示提交者提供的一个可选的参数列表。
示例
pipeline {
agent any
stages {
stage('Example') {
input {
message "Should we continue?"
ok "Yes, we should."
submitter "liangxi,lucky"
parameters {
string(name: 'PERSON', defaultValue: 'liangxi', description: 'Who should I say hello to?')
}
}
steps {
echo "Hello, ${PERSON}, nice to meet you."
}
}
}
}
过程
日志输出
Started by user admin
[
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/input
[Pipeline] {
[
[
[
Input requested
Approved by admin
[
[
[
Hello, liangxi, nice to meet you.
[
[
[
[
[
[
[
Finished: SUCCESS
6.Parallel
Declarative Pipeline 近期新增了对并行嵌套 stage 的支持,对耗时长,相互不存在依赖的 stage可以使用此方式提升运行效率。除了 parallel stage,单个 parallel 里的多个 step 也可以使用并行的方式运行
是否并行构建
示例
pipeline{
agent any
stages{
stage('Non-parallel Stage'){
steps{
echo 'This stage will be executed first'
}
}
stage('Parallel Stage'){
when{
branch 'master'
}
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"
}
}
}
}
}
}
日志输出
Started by user admin
[
[
Running on Jenkins in /var/jenkins_home/workspace/Parallel
[
[
[
[
This stage will be executed first
[
[
[
[
Stage "Parallel Stage" skipped due to when conditional
[
[
[
[
[
[
[
Stage "branch A" skipped due to when conditional
[
Stage "Branch B" skipped due to when conditional
[
[
[
[
[
[
[
[
[
[
[
Finished: SUCCESS
三、Pipeline Scripted语法
script Pipeline 提供了一组预定义的指令和块,使得构建、测试、部署等常见任务的编写变得更加容易。这种语法风格非常适合于简单到中等复杂度的流水线,并且可读性较高。它的主要优点是易于上手、易于理解和维护,并且具有一定的安全性,可以限制流水线的操作范围。
选择 Declarative Pipeline 还是 Scripted Pipeline 取决于你的具体需求。如果你的流水线相对简单,且易于使用和理解,则 Declarative Pipeline 是一个不错的选择。如果你需要更高级的功能和更大的灵活性,或者需要与外部系统进行复杂的交互,则 Scripted Pipeline 可能更适合你的需求。
示例
node('testhan') { #testhan为以上设置的Pod模板标签
stage('Clone') {
echo "1.Clone Stage" #第一步克隆代码
git url: "https://gitee.com/howehonkei/jenkins-sample" #gitee地址
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
}
}
stage('Test') {
echo "2.Test Stage" #打印2.Test Stage
}
stage('Build') { #构建镜像
echo "3.Build Docker Image Stage"
sh "docker build -t 192.168.1.130/jenkins-demo/jenkins-demo:${build_tag} ." #构建后的名字:仓库地址/项目名/镜像名:版本号
}
stage('Push') { #上传到镜像仓库
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerharbor',passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login 192.168.1.130 -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push 192.168.1.130/jenkins-demo/jenkins-demo:${build_tag}"
}
}
stage('Deploy to dev') {
echo "5. Deploy DEV"
sh "sed -i 's//${build_tag}/' k8s-dev-harbor.yaml "
sh "kubectl apply -f k8s-dev-harbor.yaml --validate=false"
}
stage('Promote to qa') {
def userInput = input(
id: 'userInput',
message: 'Promote to qa?', #是否部署到qatest测试环境
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YESnNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") { #如果是则部署,如果不是则exit退出
sh "sed -i 's//${build_tag}/' k8s-qa-harbor.yaml "
sh "kubectl apply -f k8s-qa-harbor.yaml --validate=false"
sh "sleep 6"
sh "kubectl get pods -n qatest"
} else {
//exit
}
}
stage('Promote to pro') {
def userInput = input(
id: 'userInput',
message: 'Promote to pro?', #是否部署到pro生产环境,如果是则部署,如果不是,则退出
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YESnNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's//${build_tag}/' k8s-prod-harbor.yaml "
sh "kubectl apply -f k8s-prod-harbor.yaml --record --validate=false"
}
}
}
将上面的pipeline变成声明式语法
pipeline{
agent{
node{
label 'testhan'
}
}
stages{
stage('Clone'){
steps{
echo "1.Clone Stage"
git url: "https://gitee.com/howehonkei/jenkins-sample"
script{
build_tag=sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim())
}
}
}
stage('Test'){
steps{
echo "2.Test Stage"
}
}
stage('Build'){
steps{
echo "3.Build Docker Image Stage"
sh "docker build -t xuegod/jenkins-demo:${build_tag}"
}
}
stage('Push'){
steps{
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'dockerharbor',passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login 192.168.1.130 -u ${dockerHubUser} -p ${dockerHubPassword}"
sh "docker push 192.168.1.130/jenkins-demo/jenkins-demo:${build_tag}"
}
}
}
stage('Deploy to dev'){
steps{
echo "5. Deploy DEV"
sh "sed -i 's//${build_tag}/' k8s-dev-harbor.yaml "
sh "kubectl apply -f k8s-dev-harbor.yaml --validate=false"
}
}
stage('Promote to qa') {
steps{
def userInput = input(
id: 'userInput',
message: 'Promote to qa?', #是否部署到qatest测试环境
parameters: [
choice(
choices: "YESnNO"
description: 'Select an option'
name: 'ENV'
)
]
)
echo "This is a deploy step to ${userInput}"
when {
expression{
userInput == 'YES'
}
}
steps{
sh "sed -i 's//${build_tag}/' k8s-qa-harbor.yaml "
sh "kubectl apply -f k8s-qa-harbor.yaml --validate=false"
sh "sleep 6"
sh "kubectl get pods -n qatest"
}
}
}
stage("Promote to pro"){
steps{
def userInput = input(
id: 'userInput',
message: 'Promote to pro?', #是否部署到pro生产环境,如果是则部署,如果不是,则退出
parameters: [
choice(
description: 'select an option'
choices: "YESnNO",
name: 'Env'
)
]
)
echo "This is a deploy step to ${userInput}"
when{
expression{
userInput == 'YES'
}
}
steps{
sh "sed -i 's//${build_tag}/' k8s-prod-harbor.yaml "
sh "kubectl apply -f k8s-prod-harbor.yaml --record --validate=false"
}
}
}
}
}