Jenkins 進階篇 – 任務關聯
有時候我們的一個任務裡面會進行很多的步驟,例如構建一個後端的 Java 服務,可能會有程式碼靜態掃描,靜態掃描通過後會打包成 jar 或者 war 文件,打包成功後可能還會對製品進行存檔備份,然後可能會製作容器鏡像……,這些所有的內容完全可以在一個任務中完成,也可以拆分成多個任務分步驟進行。但是將複雜任務拆分成多個任務後,會有一些附帶的其他問題,可能沒法很好地利用 Jenkins 的多節點優勢,當你的第二個任務要使用第一個任務的工作空間的文件時,你必須要確保這兩個任務要在同一個 Jenkins 節點上執行,因為如果兩個任務不在同一個節點上運行,但是第二個任務又需要使用第一個任務的工作空間的文件時就會出問題,第二個任務找不到第一個任務的工作空間。
所以若非必要就不要對任務進行拆分,如果要拆分那就要確保關聯的任務都在同一個節點運行,或者任務之間沒有對工作空間的依賴。對於如何確保關聯任務在同一個節點運行,可以使用 Node and Label parameter
插件來實現。接下來就演示關聯任務的構建與參數傳遞。
我們創建兩個自由風格的任務,任務 a 和 b 。在做關聯任務配置之前我們先安裝兩個 Jenkins 插件:Parameterized Trigger
和 Node and Label parameter
。 Parameterized Trigger
是用於關聯任務之間的觸發和參數傳遞, Node and Label parameter
是用於解決關聯任務綁定到同一個節點執行。插件安裝完成後重啟下 Jenkins 服務,用擁有管理許可權的 Jenkins 帳號訪問 //<jenkins-host>/restart
即可,等待重啟完成後開始對兩個關聯任務進行配置。
創建兩個自由風格的任務:
a 任務的配置如下,其中【構建】部分的 shell 命令後面兩行先注釋屏蔽不執行。同時在【構建】裡面增加一個步驟【Trigger/call builds on other projects】用來觸發其他任務的構建,填入子任務的名稱和要傳遞給子任務的參數,如果子任務有多個則用英文逗號分隔。
# a任務構建部分增加執行shell命令,內容如下
echo "檢查參數:"
echo "release_tag=${release_tag}, target_platform=${target_platform}, run_test=${run_test}"
# echo "Hello Jenkins" >> a.txt
# cat a.txt
b 任務也簡單,就接收列印 a 任務傳過來的參數值,以及看看 a 任務生成的文件 a.txt 裡面的內容,執行的 shell 命令如下,暫時先將最後一行注釋掉屏蔽執行。
echo "接收到的參數:"
echo "release_tag=${release_tag}, target_platform=${target_platform}, run_test=${run_test}, parent_workspace=${parent_workspace}"
# cat ${parent_workspace}/a.txt
這樣任務 a、b 都配置好了,構建任務 a 成功後會觸發任務 b 的執行,當然任務 b 也可以自己單獨構建執行,參數內容也是由任務 b 自己掌控填寫。
單獨構建任務 b,構建時的參數輸入和輸出的參數資訊如下:
現在構建 a 任務,各個參數值如下:
看看構建日誌,我們會發現 a 任務是在主節點 master 上執行的,並且構建完成後觸發構建了 b 任務:
b 任務的執行日誌如下,從日誌可以發現 b 任務是由上游任務 a 觸發構建,並且是在另一個 Jenkins 節點上執行的,接收到的參數也是從 a 任務傳遞過來的。
現在我們將 a 、b 任務裡面執行 shell 命令後面的文件操作取消注釋,讓其執行文件操作相關命令:
# a 任務的 shell 命令內容
echo "檢查參數:"
echo "release_tag=${release_tag}, target_platform=${target_platform}, run_test=${run_test}"
echo "Hello Jenkins" >> a.txt
cat a.txt
# b 任務的 shell 命令內容
echo "接收到的參數:"
echo "release_tag=${release_tag}, target_platform=${target_platform}, run_test=${run_test}, parent_workspace=${parent_workspace}"
# cat ${parent_workspace}/a.txt
同樣的,a 任務執行完後觸發了 b 任務,但是 b 任務執行失敗了,因為 Jenkins 會根據各個節點的壓力負載情況,將任務 a、b 分別在不同的 Jenkins 節點上運行,當 b 任務查看 a 任務工作空間的文件時找不到文件,那麼 b 任務就執行失敗了。
要解決這個問題就要保證各個關聯任務不依賴於各個任務的工作空間的文件,如果關聯任務又確實需要依賴工作空間的文件,那就要將任務綁定在同一個節點運行,這就需要用 Node and Label parameter
插件來實現,該插件可以通過一個參數來定義任務要在哪個節點上運行。例如,如果我們的 a 任務在 master 節點上運行了,那麼 b 任務就也要在 master 節點上運行,才能正常訪問 a 任務工作空間的文件。
我們將 a 任務配置裡面【構建】步驟中【Trigger/call builds on other projects】的參數傳遞配置做下調整,將 a 任務的構建節點名稱傳給 b 任務,讓 b 任務也在同一個節點上運行。
release_tag=${release_tag}
target_platform=${target_platform}
run_test=${run_test}
parent_workspace=${WORKSPACE}
patent_node_name=${NODE_NAME}
然後在 b 任務增加一個 Label
或者 Node
參數,控制任務在哪個節點運行,Label 參數是根據節點標籤來匹配節點,而 Node 參數則是根據節點的名稱來匹配節點,我這裡添加了一個 Label 參數,設置如下:
做好節點綁定參數的設置後我們多次構建 a 任務,看看 a 、b 任務最後的執行日誌。
從構建的執行日誌上,我們可以看到任務 a、b 是已經綁定在同一個 Jenkins 節點上運行了。另外這一小節使用了一些 Jenkins 內置的環境變數,WORKSPACE 和 NODE_LABELS,還有一些其他的內置環境變數可以瀏覽器訪問 //<jenkins-host>/env-vars.html
進行查看,這些環境變數可以在任務配置時直接獲取使用。