Jenkins - Pipeline Job 平行處理 (一)

-- Pageviews

Jenkins - Pipeline Job 平行處理 - 執行結果

在撰寫 Pipeline Job 時,很多時候工作是沒有順序相依關係,如果純用 stage 逐一處理,略顯效率不彰。
本篇將介紹 Jenkins 使用 Groovy 撰寫 Pipeline Job 的平行處理。

Groovy Script

假設以下範例,三個 stage 沒有相依關係:

1
2
3
4
5
6
7
8
9
stage("Task 1") {
// ...
}
stage("Task 2") {
// ...
}
stage("Task 3") {
// ...
}

若沒有相依關係就可以改成平行處理,平行處理透過調用 parallel 方法實現。
parallel 調用是以 String 為 key, Delegate Method 為 Value。
範例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
parallel (
"Task 1": {
stage("Task 1") {
// ...
}
},
"Task 2": {
stage("Task 2") {
// ...
}
},
"Task 3": {
stage("Task 3") {
// ...
}
}
)

動態增加工作

可以自行建立 HashMap,再把 HashMap 傳入 parallel 方法。範例如下:

1
2
3
4
5
6
7
8
9
10
11
def tasks = [:]

for (int i = 0; i < 5; i++) {
tasks["Task ${i+1}"] = {
stage("Task ${i+1}") {
echo "Task ${i+1}"
}
}
}

parallel(tasks)

實際執行上面範例,會發現不如預期所想,echo 內容預期應該要是:

1
2
3
4
5
Task 1
Task 2
Task 3
Task 4
Task 5

實際上 echo 內容卻是:

1
2
3
4
5
Task 6
Task 6
Task 6
Task 6
Task 6

主要是因為 Delegate Method 使用的外部變數,在執行 parallel 時,早就跑完迴圈被改成 6 了。
如果真的想要在 Delegate Method 取得外部變數,建議另外用區域變數儲存,避免外部變數在執行前被改變。如下:

1
2
3
4
5
6
7
8
9
10
11
12
def tasks = [:]

for (int i = 0; i < 5; i++) {
def index = i+1
tasks["Task ${index}"] = {
stage("Task ${index}") {
echo "Task ${index}"
}
}
}

parallel(tasks)

部分平行處理

較複雜的流程可能會有部分的工作能平行處理,但之後的工作又有相依關係。
parallel 平行處理後,可以透過 stage 等待平行處理工作全部完成,再繼續往下動作。
如下範例,有兩段工作群可以平行處理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
stage ("Checkout Source Code") { }

parallel(
"Build First Module" : { stage("Build") { } },
"Build Second Module" : { stage("Build") { } },
"Build Third Module" : { stage("Build") { } },
)

stage ("Integration Test") { }

parallel(
"Deploy First Module" : { stage("Deploy") { } },
"Deploy Second Module" : { stage("Deploy") { } },
"Deploy Third Module" : { stage("Deploy") { } },
)

stage ("Commit Artifacts") { }

執行結果

如果有安裝 Blue Ocean 的話,就可以看到漂亮的圖形化平行處理執行結果: Jenkins - Pipeline Job 平行處理 - 執行結果