目錄一覽:
-
0x00 前言簡述
-
Pipeline 介紹
-
Pipeline 基礎知識
-
Pipeline 擴展共享庫
-
BlueOcean 介紹
-
0x01 Pipeline Syntax
-
(0) Groovy Basic Syntax
-
(1) Scripted Pipeline Syntax
-
Hello-World 實踐
-
變量名-Identifiers
-
字符串-String
-
數字 - Numbers
-
列表-List
-
字典 - Maps
-
條件語句 - Condition
-
異常 - Exception
-
函數 - Functions
-
語法總結
WeiyiGeek Blog - 為了能到遠方,腳下的每一步都不能少。
原文地址: https://mp.weixin.qq.com/s/i5ZetHB66rbbVEAO10Egpg
Tips : 本文章來源 Blog 站點或者 WeiyiGeek
公眾賬號 (技術交流、友鏈交換請郵我喲
),
- 微信公眾號-WeiyiGeek # 精華文章發布地址(及時發布)
- 首頁-https://weiyigeek.top # 國內有時訪問較慢
- https://weiyigeek.gitee.i # 國內訪問快但可能會有更新不及時的情況
0x00 前言簡述
Pipeline 介紹
Q: 什么是 Pipeline?
答: Pipeline(流水線)是 Jenkins 2.0 的精髓它基於Groovy語言實現的一種DSL(領域特定語言),簡而言之就是一套運行於Jenkins上的工作流框架,用於描述整條流水線是如何進行的。
它將原本獨立運行於單個或者多個節點的任務連接起來,實現單個任務難以完成的復雜流程編排與可視化
。
Q: 什么是DSL?
答: DSL即
(Domain Specific Language)
領域專用語言,專門針對一個特定的問題領域,具有建模所需的語法和語義的語言。在與問題域相同的抽象層次對概念建模。
DSL 是 Jenkins 服務特有的一個語言,底層通過 Groovy 編程語言來實現。在使用過程中,可以很好的結合 Groovy。Jenkins Job DSL Plugin 提供了豐富的API,我們可以通過這些API實現對 Jenkinis 中View、Job 等管理。
Tips: Jenkins 內置了 Groovy 的引擎,我們可以通過 Groovy 編程語言在 DSL API 中添加邏輯編程。
Q: 什么是 Groovy 語言
答: Groovy 是 Apache 旗下的一門基於 JVM 平台的動態/敏捷編程語言,在語言的設計上它吸納了 Python、Ruby 和 Smalltalk 語言的優秀特性,語法非常簡練和優美,開發效率也非常高(編程語言的開發效率和性能是相互矛盾的,越高級的編程語言性能越差,因為意味着更多底層的封裝,不過開發效率會更高,需結合使用場景做取舍)
Tips: PipeLine在Jenkins中的發展歷史
-
1.Jenkins 1.x 支持 Pipeline ,只不過是通過頁面手動配置流水線。
-
2.Jenkins 2.x 開始支持 pipeline as code ,可以通過代碼來配置流水線了。
Q: 為什么要使用Pipeline?
1.Pipeline是Jenkins2.X的最核心的特性,幫助Jenkins實現從
CI到CD
與AutoDevOps
的轉變;
2.Pipeline是一組插件它可以讓Jenkins可以實現持續交付 Pipeline的落地和實施。
3.Pipeline提供了一組可擴展的工具,通過Pipeline Domain Specific Language(DSL) syntax
可以達到 Pipeline as Code(Jenkinsfile存儲在項目的源代碼庫)的目的。
Tips: 流水線的內容包括執行編譯、打包、測試、輸出測試報告等步驟。
Tips: 持續交付Pipeline (CD Pipeline)
是將軟件從版本控制階段到交付給用戶或客戶的完整過程的自動化表現, 軟件的每一次更改(提交到源代碼管理系統)都要經過一個復雜的過程才能被發布。
Pipeline五大特性(優點)
-
代碼: Pipeline以代碼的形式實現,通常被檢入源代碼控制,使團隊能夠編輯、審查和迭代其CD流程。
-
可持續性:Jenklins重啟或者中斷后都不會影響Pipeline Job。
-
停頓:Pipeline可以選擇停止並等待構建人員的輸入或批准,然后再繼續Pipeline運行。
-
多功能:Pipeline支持現實世界的復雜CD要求,包括fork/join子進程,循環和並行執行工作的能力
-
可擴展:Pipeline插件支持其
DSL
的自定義擴展以及與其他插件集成的多個選項。
Tips: 它實現持續集成與部署、節省產品發布時間、優化部署策略、節省人力成本、以及自動化腳本復用等等;
Q: 怎樣安裝Pipeline插件?
答: 熟話說工欲善其事必先利其器,第一步當然需要安裝Jenkins使用Pipeline所需的插件;
Jenkins pipeline 相關插件安裝: 打開 Jenkins 找到 【系統管理】->【插件管理】->【可選插件】
然后在搜索框輸入 Pipeline
Pipeline 命令行接口 雜項 代理啟動器和控制器 構建觸發器 2.6 2 年 3 月 ago
# 說明:一套插件,讓您編排自動化,簡單或復雜。更多細節請參閱Jenkins的 Pipeline代碼。
Pipeline 基礎知識
基礎說明:
Pipeline 腳本是由 Groovy 語言結合 DSL 語言實現的。
Pipeline 支持兩種語法:
Declarative Pipeline (聲明式 - 2.5 引入)
和Scripted Pipeline (腳本式)
語法Pipeline 也有兩種創建方法:
方式1、在 Jenkins 的 Web UI 界面中輸入腳本;
方式2、通過創建一個 Jenkinsfile 腳本文件(
Groovy 語言結合 DSL 開發
)放入項目源碼庫中 (推薦在 Jenkins 中直接從源代碼控制(SCMD) 中直接載入 Jenkinsfile Pipeline
)
語法差異:
描述: 最初創建 Jenkins Pipeline 時 Groovy 語言被選為基礎。Jenkins長期以來一直提供嵌入式Groovy引擎,以為管理員和用戶提供高級腳本功能。另外Jenkins Pipeline的實現者發現Groovy是構建現在稱為"腳本 Pipelin" DSL的堅實基礎。
由於它是功能齊全的編程環境,因此腳本化 Pipeline為Jenkins用戶提供了極大的靈活性和可擴展性。Groovy學習曲線通常不是給定團隊的所有成員所希望的,因此創建了聲明式 Pipeline,以為編寫Jenkins Pipeline提供更簡單,更自以為是的語法。
兩者基本上是下面的相同 Pipeline子系統。它們都是“ Pipeline作為代碼”的持久實現。他們都可以使用內置在Pipeline中或由插件提供的步驟。兩者都可以利用 共享庫
但是它們的區別在於語法和靈活性。聲明性限制使用更嚴格和預定義的結構為用戶提供的功能,使其成為更簡單的連續交付 Pipeline的理想選擇。腳本化腳本提供的限制非常少,以至於對結構和語法的唯一限制往往是由Groovy本身定義的,而不是由任何特定於 Pipeline的系統定義的,因此,它成為高級用戶和要求更復雜的用戶的理想選擇。顧名思義,聲明性流水線鼓勵使用聲明性編程模型,而腳本 Pipeline 遵循更強制性的編程模型。
Q: 選擇Declarative Pipeline
還是Scripted Pipeline
?
答: 最開始
Pipeline plugin
僅支持Scripted Pipeline
一種腳本類型,而Declarative Pipeline
為Pipeline plugin在2.5版本之后新增的一種腳本類型與原先的Scripted Pipeline
一樣都可以用來編寫腳本。由於在我們使用BlueOcean流水線UI插件后,Declarative Pipeline 與 BlueOcean 腳本編輯器是可以兼容使用,
並且在eclarative Pipeline中,也是可以內嵌Scripted Pipeline代碼的
,所以通常建議使用Declarative Pipeline
(英 /dɪˈklærətɪv/
)的方式進行編寫
Declarative pipeline和Scripted pipeline的比較?
-
1.共同點:
-
聲明式和腳本式流水線都是 DSL 語言,用來描述軟件交付流水線的一部分。
-
兩者都能夠使用pipeline內置的插件或者插件提供的step步驟部分。
-
兩者都可以利用共享庫擴展。
-
2.區別: 兩者不同之處在於語法和靈活性;
-
Declarative pipeline 語法更嚴格 (
例如必須以 pipeline 關鍵詞打頭
),有固定的組織結構但更容易生成代碼段,所以它成為用戶更理想的選擇。 -
Scripted pipeline 語法更加靈活,因為Groovy本身只能對結構和語法進行限制,對於更復雜的pipeline來說,用戶可以根據自己的業務進行靈活的實現和擴展。
Tips: 腳本式語法的確靈活、可擴展,但是也意味着更復雜。而聲明式語法供更簡單、更結構化(more opinionated)的語法 (模塊化的感覺
)。
Pipeline 擴展共享庫
描述: 由於流水線被組織中越來越多的項目所采用,常見的模式很可能會出現在多個項目之間共享流水線, 共享流水線有助於減少冗余並保持代碼 “DRY(Don’t Repeat Yourself)”
。
Q: 如何定義共享庫?
答: 我們將一些通用的代碼或者代碼包,封裝定義為底層代碼庫,方便流水線創建。
特定的目錄結構:
(root)
+- src # Groovy source files
| +- org
| +- foo
| +- Bar.groovy # for org.foo.Bar class
+- vars
| +- foo.groovy # for global 'foo' variable
| +- foo.txt # help for 'foo' variable
+- resources # resource files (external libraries only)
| +- org
| +- foo
| +- bar.json # static helper data for org.foo.Bar
目錄結構解析:
-
1、src 目錄應該看起來像標准的 Java 源目錄結構。當執行流水線時,該目錄被添加到類路徑下。
-
2、vars 目錄定義可從流水線訪問的全局變量的腳本。 每個 *.groovy 文件的基名應該是一個 Groovy (~ Java) 標識符, 通常是 駝峰命名法(camelCased)。 匹配 *.txt, 如果存在可以包含文檔, 通過系統的配置標記格式化從處理 (所以可能是 HTML, Markdown 等,雖然 txt 擴展是必需的)。這些目錄中的 Groovy 源文件 在腳本化流水線中的 “CPS transformation” 一樣。
-
3、resources 目錄允許從外部庫中使用 libraryResource 步驟來加載有關的非 Groovy 文件。 目前,內部庫不支持該特性。
-
4、根目錄下的其他目錄被保留下來以便於將來的增強。
Q: 如何將將共享庫設置為全局共享庫?
描述: 在Jenkins 管理頁面中的 “Configure System” 頁面中的 “Global Pipeline Libraries” 中設置全局共享庫。
Q: 如何使用封裝的代碼庫
答: Jenkinsfile 文件中需要使用 @Library 注解,指定庫的名字。另外關於代碼庫的動態加載、版本管理和檢索方式等,請見官網。
Q: 如何編寫自己的 Jenkins 共享庫,共享庫中的變量作用域?
答: 其他關於寫庫的訪問步驟、定義全局變量 請見官網。
BlueOcean 介紹
Q: 什么是BlueOcean?
A: BlueOcean 重新考慮了 Jenkins 的用戶體驗而重新設置UI界面,從而更加直觀的展現Pipeline各流程執行情況;
BlueOcean由Jenkins Pipeline設計,但仍然兼容自由式工作,減少了團隊成員的混亂,增加了清晰度。
Q: 為啥要使用BlueOcean?
連續交付(CD)Pipeline的復雜可視化,允許快速和直觀地了解Pipeline的狀態。
Pipeline編輯器通過引導用戶直觀和可視化的過程創建Pipeline,使創建Pipeline平易近人。
個性化,以適應團隊每個成員的角色需求。
需要干預和/或出現問題時確定精度。BlueOcean顯示了Pipeline需要注意的地方,便於異常處理和提高生產率。
用於分支和拉取請求的本地集成可以在GitHub和Bitbucket中與其他人進行代碼協作時最大限度提高開發人員的生產力。
Q: 如何安裝BlueOcean?
A: 同樣是在插件中搜索 ”Blue Ocean“ 下載安裝即可
Blue Ocean - 外部工具集成 用戶界面 - BlueOcean Aggregator - 1.24.3 2 月 5 天 ago
0x01 Pipeline Syntax
(0) Groovy Basic Syntax
描述: 我們前面說過不管是聲明式還是腳本式都是基於Groovy語言,所以學習 Groovy 基礎知識是必須的。
-
1.雖然Groovy同時支持靜態類型和動態類型,但是在定義變量時,在Groovy中我們習慣使用def關鍵字
def x="abc"
def y=1
-
2.不像 Java語法語句,Groovy語句最后的分號不是必需的。
-
3.Groovy中的方法調用可以省略括號,比如System.out.println "Hello world"。
System.out.println x
println t
-
4.支持單引號、雙引號。雙引號支持插值(變量),單引號不支持。
-
5.支持三引號。三引號分為三單引號和三雙引號。它們都支持換行,區別在於只有三雙引號支持插值(變量)。
def var = """
This is Variable!
Test defiend
"""
-
6.支持函數。
def getSecure(String Ticket_Token) {
def token = "Ticket Token is " + Ticket_Token
return token
}
println getSecure("weiyigeek") //Ticket Token is weiyigeek
-
7.支持閉包。
// # 閉包的定義方法:
def codeBlock = {print "hello world!"}
// codeBlock() //
// # 閉包的另類用法:
// 定義一個stage函數
def stage(String name, closue) {
println name
def closue() {
println "閉包調用的 closue function!"
}
}
stage("stage name",{println "closue"})
-
8.支持類定義和實例化。
class Greet {
def name
Greet(who) { name = who[0].toUpperCase() + who[1..-1] }
def salute() { println "Hello " + name + "!" }
}
g = new Greet('world') // create object
g.salute() // Hello World!
(1) Scripted Pipeline Syntax
描述: Scripted Pipeline 是基於 groovy 的一種 DSL
語言相比於 Declarative pipeline,它為jenkins用戶提供了更巨大的靈活性和可擴展性。
Scripted Pipeline 基礎結構說明:
-
Node:節點,一個 Node 就是一個 Jenkins 節點,Master 或者 Agent,是執行 Step 的具體運行環境,比如我們之前動態運行的 Jenkins Slave 就是一個 Node 節點
-
Stage:階段,一個 Pipeline 可以划分為若干個 Stage,每個 Stage 代表一組操作,比如:Build、Test、Deploy,Stage 是一個邏輯分組的概念,可以跨多個 Node
-
Step:步驟,Step 是最基本的操作單元,可以是打印一句話,也可以是構建一個 Docker 鏡像,由各類 Jenkins 插件提供,·
比如命令:sh 'make',就相當於我們平時 shell 終端中執行 make 命令一樣。
(注意:此處Step不是cripted Pipeline關鍵字而是代表一條執行語句)
Scripted Pipeline 語法示例:
// Jenkinsfile (Scripted Pipeline)
// #結構1
node {
// @變量定義
def mvnHome
// #結構2
stage('Preparation') {
// # 結構3 - 它就是 Step 基本操作單元
echo "Scripted Pipeline"
}
}
Tips : 注釋(Comments)和Java一樣,支持單行(使用//)、多行(/* */)和文檔注釋(使用/** */)
。
Hello-World 實踐
Step 1.在Jenkins的WEB UI -> 新建任務 -> simple-pipeline-demo 任務名稱 -> 選擇流水線 -> 確定
Step 2.在 Dashboard -> simple-pipeline-demo -> 流水線 -> 可以選擇pipeline script(或者直接從scm拉取Jenkinsfile)此處為了演示只是簡單的了解 -> 應用保存
# Scripted Pipeline 腳本式
node {
stage('Clone') {
echo "1.Clone Stage"
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Stage"
}
stage('Deploy') {
echo "4. Deploy Stage"
}
}
Step 3.立即構建 -> 查看階段視圖 (或者利用blue-Ocean插件)進行更加直觀的查看 -> 觀察構建的日志信息
Started by user admin
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/simple-pipeline-demo
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Clone)
[Pipeline] echo
1.Clone Stage
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] echo
2.Test Stage
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Build)
[Pipeline] echo
3.Build Stage
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Deploy)
[Pipeline] echo
4. Deploy Stage
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
PS : 你可以選擇使用BlueOcean或者jenkins原生的流水控制台展示兩則並不沖突,但是需要注意Scripted pipeline不完全兼容BlueOcean
;
變量名-Identifiers
描述: 標識符(Identifiers)也稱變量名, 以字母、美元符號$或下划線_開始
,不能以數字開始。
例如以下是可用的標識符:
def name
def item3
def with_underscore
def $dollarStart
以下是不可用的標識符:
def 3tier // 不能以數字開始
def a+b // "+"號是非法字符
def a#b // #號也不是可用的字符
Tips : 在點號后是可以使用關鍵字作為標識符時產生org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
錯誤;
foo.as
foo.assert
foo.break
foo.case
foo.catch
字符串-String
描述: 在Groovy中字符串有兩種類型,一種是Java原生的java.lang.String
;另一種是groovy.lang.GString
,又叫插值字符串(interpolated strings)。
-
(1) 單引號字符串(Single quoted string)
在Groovy中,使用單引號括住的字符串就是java.lang.String,不支持插值:
def name = 'yjiyjgie'
println name.class // class java.lang.String
-
(2) 三單引號字符串(Triple single quoted string)
使用三單引號括住字符串支持多行,也是java.lang.String實例,在第一個’‘’起始處加一個反斜杠\可以在新一行開始文本:
def strippedFirstNewline = '''line one
line two
line three
'''
// 可以寫成下面這種形式,可讀性更好
def strippedFirstNewline = '''\
line one
line two
line three
'''
-
(3) 雙引號字符串(Double quoted string)
如果雙引號括住的字符串中沒有插值表達式(interpolated expression),那它就是java.lang.String;如是有插值表達式,那它就是groovy.lang.GString:
def normalStr = "yjiyjige" // 這是一個java.lang.String
def interpolatedStr = "my name is ${normalStr}" // 這是一個groovy.lang.GString
-
(4) 字符串插值(String interpolation)
在Groovy所有的字符串字面量表示中,除了單引號字符串和三單引號字符串,其他形式都支持字符串插值。字符串插值也即將占位表達式中的結果最終替換到字符串相應的位置中:
def name = 'Guillaume' // a plain string
def greeting = "Hello ${name}" // name變量的值會被替換進去
assert greeting.toString() == 'Hello Guillaume'
//當使用點號表達式時,可以只用$代替${}:
def person = [name: 'Guillaume', age: 36]
println "$person.name is $person.age years old"
補充說明:
// 插值占位符中還支持閉包,而閉包的一個好處是惰性求值(lazy evaluation):
def number = 1
def eagerGString = "value == ${number}" // 普通形式
def lazyGString = "value == ${-> number}" // 這是一個閉包
println eagerGString // == "value == 1"
println lazyGString // == "value == 1"
number = 2
println eagerGString // == "value == 1" // eagerGString已經被固定下來了
println lazyGString // == "value == 2" // lazyGString的值會被重新計算
Tips: GString與String的hashCode是不一樣的即使他們最終結果一樣。所以在Map中不應該用GString去做元素的Key,而又使用普通的String去取值;
// 當一個方法的需要一個java.lang.String變量,而我們傳遞的是一個groovy.lang.GString實例時,GString的toString方法會被自動調用,看起來像我們可以直接將一個GString賦值給一個String變量一樣。
def key = "a"
def m = ["${key}": "letter ${key}"] // key類型是一個GString
assert m["a"] // == null // 用一個普通String類型的key去取值取代的值為null 而並非 letter a
Tips : 對於輸出對象帶有指定方法時如有需要拼接其它字符串需要以${對象.方法}
進行包含;
def number = 3.14
println "$number.toString()" // 這里會報異常,因為相當於"${number.toString}()"
println "${number.toString()} -- Other String、" // 這樣就正常了
數字 - Numbers
描述: 當使用def指明整數字面量時,變量的類型會根據數字的大小自動調整:
// 如果要強制指明一個數字的字面量類型,可以給字面量加上類型后綴:
BigInteger 使用G或g
Long 使用L或l
Integer 使用I或i
BigDecimal 使用G或g
Double 使用D或d
Float 使用F或f
def a = 1
assert a instanceof Integer
// Integer.MAX_VALUE
def b = 2147483647
assert b instanceof Integer
// Integer.MAX_VALUE + 1
def c = 2147483648
assert c instanceof Long
// Long.MAX_VALUE
def d = 9223372036854775807
assert d instanceof Long
// Long.MAX_VALUE + 1
def e = 9223372036854775808
assert e instanceof BigInteger
Tips : 為了精確地計算小數,在Groovy中使用def聲明的小數是BigDecimal類型的:
def decimal = 123.456
println decimal.getClass() // class java.math.BigDecimal
列表-List
描述:默認情況下Groovy的列表使用的是java.util.ArrayList
,用中括號[]括住,使用逗號分隔:
def numbers = [1, 2, 3]
println numbers.getClass() # // class java.util.ArrayList
# 如果要使用其它類型的列表(如:LinkedList)可以使用as操作符或顯式分配給一個指定類型的變量:
def arrayList = [1, 2, 3] # // 默認類型
# assert arrayList instanceof java.util.ArrayList
def linkedList = [2, 3, 4] as LinkedList # // 使用as操作符
# assert linkedList instanceof java.util.LinkedList
LinkedList otherLinked = [3, 4, 5] # // 顯式指明類型
# assert otherLinked instanceof java.util.LinkedList
Groovy重載了列表的[]和<<操作符,可以通過List[index]訪問指定位置元素,也可以通過List << element
往列表末尾添加元素:
def letters = ['a', 'b', 'c', 'd']
assert letters[0] // == 'a'
assert letters[1] // == 'b'
assert letters[-1] // == 'd' 從后面訪問 倒數第一個
assert letters[-2] // == 'c' // 從后面訪問 倒數第二個
// 元素修改
letters[2] = 'C'
assert letters[2] // == 'C'
letters << 'e' // 往最后面添加元素
assert letters[4] == 'e'
assert letters[-1] == 'e'
assert letters[1, 3] == ['b', 'd'] // 提取指定元素
assert letters[2..4] == ['C', 'd', 'e'] // 支持范圍(ranges)操作
// 二維列表
def multi = [[0, 1], [2, 3]]
assert multi[1][0] == 2
字典 - Maps
描述: Groovy使用中括號[]來定義字典,元素需要包含key和value使用冒號分隔,元素與元素之間用逗號分隔:
// key部分其實是字符串
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
assert colors['red'] == '#FF0000' // 使用中括號訪問
assert colors.green == '#00FF00' // 使用點表達式訪問
// 兩種方式
colors['pink'] = '#FF00FF'
colors.yellow = '#FFFF00'
assert colors.pink // == '#FF00FF'
assert colors['yellow'] // == '#FFFF00'
assert colors instanceof java.util.LinkedHashMap // 默認使用LinkedHashMap類型
在上邊的例子中,雖然沒有明確的使用字符串’red‘、’green‘
,但Groovy會自動把那些key轉化為字符串。並且在默認情況下,初始化字典時key也不會去使用已經存在的變量:
def keyVal = 'name'
def persons = [keyVal: 'Guillaume'] // 非常注意: 此處的key是字符串keyVal而不是name
assert !persons.containsKey('name')
assert persons.containsKey('keyVal')
// 如果要使用一個變量作為key,需要用括號括住:
def keyVal = 'name'
def persons = [(keyVal): 'Guillaume'] // 相當於[ 'name' : 'Guillaume' ]
assert persons.containsKey('name')
assert !persons.containsKey('keyVal')
條件語句 - Condition
if 語句
第一個決策語句是 if 語句。這種說法的一般形式是
// # syntax
if(condition) {
statement #1
statement #2
...
}
例子:
//@ 流程控制Groovy表達式如if/else條件語句
if (env.BRANCH_NAME == 'master') {
echo 'I only execute on the master branch'
} else {
echo 'I execute elsewhere'
}
For循環
for 語句用於遍歷一組值。for 語句通常以以下方式使用。
for(variable declaration;expression;Increment) {
statement #1
statement #2
…
}
例子:
for(int i = 0;i<5;i++) {
println(i);
}
Switch 語句
Swict 語句用於條件判斷, 基礎語法如下
switch () {
case '1':
echo 1
break
case '2':
echo 2
break
default:
}
異常 - Exception
描述:流程控制是Groovy的異常處理機制,在實際過程中建議同時使用try...catch..finally進行捕獲異常;
try {
helloWorld() // == Scripted Pipeline - Hello Wrold - STARTED - 1024!
dir("place") {
sh 'id' // == uid=112(jenkins) gid=117(jenkins) groups=117(jenkins)
}
} catch (e) {
// If there was an exception thrown, the build failed
currentBuild.result = "FAILED"
throw e
} finally {
println "success or failure, always send notifications" // == Success or failure, always send notifications
}
函數 - Functions
描述:Groovy中的方法是使用返回類型或使用def關鍵字定義的, 方法可以接收任意數量的參數並定義參數時不必顯式定義類型,可以添加修飾符如public,private和protected
。
Tips : 注意事項
-
默認情況下如果未提供可見性修飾符則該方法為public。
-
注意: 函數定義不能被包含在
node{}塊
之中, 而函數調用是在node { stage() { 函數名稱} }
之中的; -
注意: 函數參數有定義默認值
簡單示例:
node {
stage('函數調用') {
// 函數名稱
methodName
}
}
def methodName(String param = 'default1',int number = 1024) {
//Method code
println "Hello Wrold function - ${param} - ${age}!"
}
參考地址: https://stackoverflow.com/questions/40870657/groovy-method-definition-not-expected-here
語法總結
描述: 此次對 Scripted Pipeline
語法的使用進行一個簡單的總結, 或許在后面的Declarative Pipeline中可以進行使用;
node {
// 變量定義
def foo
// 字符串
def project="HelloWorld"
// 單引號字符串(Single quoted string)不能解析變量
def name='weiyigeek - ${project}'
// 三單引號字符串(Triple single quoted string)不能解析變量
def line='''\
Line one
Line ${project}
'''
// 定義字典Maps
def person = [name: 'WeiyiGeek', age: 96]
stage('Scripted Pipeline Syntax') {
// (1) 變量聲明
foo="Identifiers"
// (2) 變量調用
echo "${foo} -- ${project}" // == Identifiers -- HelloWorld
// (3) 字符串輸出
echo "my name is ${name}" // == my name is weiyigeek - ${project}
// (4) 多行字符串輸出
echo "${line}" /* ==
Line one
Line ${project}
*/
// (5) 變量對象屬性輸出
echo "$person.name is $person.age years old" // == WeiyiGeek is 96 years old
name = 'WeiyiGeek'
project = "my name is ${name}"
def greeting = "Hello ${name}" // name變量的值會被替換進去
// (6) 字符串格式化聲明
assert greeting.toString()
println "${project.toString()}" //調用方法后直接輸出 == my name is WeiyiGeek
// 閉包
def number = 1
def eagerGString = "value == ${number}" // 普通形式
def lazyGString = "value == ${-> number}" // 這是一個閉包
println eagerGString // == value == 1
println lazyGString // 此處輸出為空 (value == 1)
number=1024
echo "-----------------"
println eagerGString // == value == 1
println lazyGString // 此處輸出為空 (value == 1024)
// (7) 變量類型輸出
println "變量name類型:"+name.class+", \n 變量project類型: "+project.class+", \n 變量greeting類型: "+greeting.class
/* == 變量name類型:class java.lang.String,
變量project類型: class org.codehaus.groovy.runtime.GStringImpl,
變量greeting類型: class org.codehaus.groovy.runtime.GStringImpl */
// (8) 數值類型與類型強轉
def decimal = 123.456
println "${decimal.getClass()} -- ${decimal} " // == class java.math.BigDecimal -- 123.456
//assert decimal instanceof BigDecimal
// (9) 數組列表
def arrayList = [1,2,3,"number"]
println arrayList[0] // == 1
arrayList << '5'
echo "assert ${arrayList[0]} --- ${arrayList[-2]} --- ${arrayList[-1]}" // == assert 1 --- number --- 5
def multi = [[0, 1], [2, 3]] // 二維數組
echo "assert ${multi[1][0]}" // == 2
// (10) 字典Map
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
colors['pink'] = '#FF00FF'
colors.yellow = '#FFFF00'
println "colors 類型 : "+ colors.pink.class + ", assert colors.pink : " + colors.pink + ",assert colors['yellow'] : " + colors['yellow']
/* colors 類型 : class java.lang.String, assert colors.pink : #FF00FF,assert colors['yellow'] : #FFFF00 */
// 如果要使用一個變量作為key(缺省為字符串),需要用括號括住:
def keyVal = 'name'
def persons = [(keyVal): 'WeiyiGeek'] // 相當於[ 'name' : 'WeiyiGeek' ]
println "key is name: " + persons.containsKey('name') + " , Key not is KeyVal : " + !persons.containsKey('keyVal')
/* key is name: true , Key is KeyVal : true */
// (11) 條件語句 - if - for - switch
if ( keyVal == 'name' ) {
echo "keyVal value is name" // == keyVal value is name
} else {
echo "keyVal value is not name"
}
if (env.BRANCH_NAME == 'master') {
echo 'I only execute on the master branch'
} else {
echo 'I execute elsewhere'
}
for (int i=0; i < 5; i++) {
println arrayList[i] // 如果越界顯示則 `null` // == 1,2,3,number,5
}
def option = "deploy"
switch ("${option}") {
case 'deploy':
echo "deploy" // == deploy
break
case 'rollback':
echo "rollback"
break
default:
echo "default"
}
// (12) 異常捕獲
try {
helloWorld() // == Scripted Pipeline - Hello Wrold - STARTED - 1024!
dir("place") {
sh 'id' // == uid=112(jenkins) gid=117(jenkins) groups=117(jenkins)
}
} catch (e) {
// If there was an exception thrown, the build failed
currentBuild.result = "FAILED"
throw e
} finally {
println "success or failure, always send notifications" // == Success or failure, always send notifications
}
// (13)函數調用
helloWorld("weiyigeek") /* Scripted Pipeline - Hello Wrold - weiyigeek - 1024! */
}
}
// (13) 函數聲明定義時 不能包括在node中
def helloWorld (String username = 'STARTED',int age = 1024) {
println "Scripted Pipeline - Hello Wrold - ${username} - ${age}!"
}
WeiyiGeek Blog - 為了能到遠方,腳下的每一步都不能少。
Tips : 本文章來源 Blog 站點或者 WeiyiGeek
公眾賬號 (友鏈交換請郵我喲
):
-
微信公眾號-WeiyiGeek` # 精華文章發布地址
-
https://weiyigeek.top # 采用cloudflare CDN 國內有時訪問較慢
-
https://weiyigeek.gitee.io # 國內訪問快可能會有更新不及時得情況
Tips: 更多學習筆記文章請關注
WeiyiGeek
公眾賬號
【微信公眾號關注(點擊)】
【郵箱聯系: Master#weiyigeek.top】