在 GitLab CI 中每個工作 (job) 最重要的區段,大概可以說是 script
的部分,每個工作都必須有 script 的宣告,才能夠運作,整份 .gitlab-ci.yml
也才可以正確執行;GitLab CI 的 script 使用上,只能一行一行的設定嗎?這一篇將針對 script 的一些小細節作說明。
一般來說,在執行 script 時,系統或程式回傳的狀態值,只要是「 非 0 」,就代表該指令執行錯誤,後續的指令也就不繼續執行。因此,當有自訂錯誤碼的需求時,就可以利用這一點,其實作的方法也很簡單,只要 exit
後面接續非 0 的數字即可。舉例來說:
job:
image: 'ubuntu:20.04'
variables:
WILL_EXECUTE: 'RUN'
script:
- if [[ "${WILL_EXECUTE}" != "RUN" ]]; then echo "can not run" && exit 10; fi;
- echo "RUN RUN RUN"
上面的這個例子,當變數 WILL_EXECUTE
的數值為 RUN
的時候,則在畫面上顯示 RUN RUN RUN
,當不為 RUN
時,則顯示 can not run
並且產生 response code 10,讓 runner 顯示錯誤。在這邊也可以透過手動啟動流水線(Pipeline)來刻意設定 WILL_EXECUTE
讓他對應的數值不為 RUN
。
而後,就可以在執行結果中看到,因 WILL_EXECUTE
內容不為 RUN
因此畫面呈現了 can not run
並且錯誤代碼為 10 後續的工作也沒有再進行了。
當可以自行設定錯誤代碼時,就可以透過 script 來設計產生錯誤的條件,進而最佳化整個工作流程。
在上面的例子中,可以發現在設定判斷式時,因為內容都集中在同一行中,導致 script 可閱讀性降低。那麼,在 script
裡頭,可以怎麼撰寫多行 (multi-line) 的指令呢?
以上面的例子,因為是判斷式,因此個人通常會使用多個 script 並且以 space 作為 indent,修改後如下:
job:
image: 'ubuntu:20.04'
variables:
WILL_EXECUTE: 'RUN'
script:
- if [[ "${WILL_EXECUTE}" != "RUN" ]]; then
- echo "can not run";
- exit 10;
- fi;
- echo "RUN RUN RUN"
這樣修改帶來額外的好處是,如果發生錯誤的是 echo "can not run"
這部分的 script,也可以在發生錯誤時,快速的找到真正錯誤的位置。
另外像是在 script 中要進行打包或壓縮多個檔案及資料夾時,也會透過希望將資料夾或檔案以一行一個的方式顯示,但壓縮打包的指令,通常需要一次完成,這時候就無法如上使用多個 script 來完成。如壓縮打包指令 tar -pcvf FILE_NAME.tgz readme.md changelog.md src
,希望將 readme.md
、changelog.md
及 src
資料夾打包為 FILE_NAME.tgz
。這時候在 script
中可以怎麼完成呢?
job:
image: 'ubuntu:20.04'
variables:
WILL_EXECUTE: 'RUN'
script:
- "tar -pcvzf ${RELEASE_FILE_NAME} \
readme.md \
changelog.md \
src"
如上面的指令,可以透過 shell script 可以透過 \
符號做跨行串接的特性進行。
在 GitLab CI 官方手冊上,也有提到使用 YAML 語法來作多行指令的呈現,其是透過 |
符號 或 >
符號來標示為「多行」:
首先是使用 |
符號的範例:
job:
script:
- |
echo "First command line."
echo "Second command line."
echo "Third command line."
呈現的結果如下:
其次是使用 >
指令的範例:
job:
script:
- >
echo "First command line
is split over two lines."
echo "Second command line."
以及
job:
script:
- echo "First command line
is split over two lines."
echo "Second command line."
上面兩個範例的效果是一致的,其呈現的結果如下:
另外,在 YAML 檔案裡頭,要呈現多行文字,還有一些參考範例,可以查看YAML Multiline Strings上的其它範例。
在 runner 輸出的畫面中,呈現系統上亮綠色深綠色以及自行輸出的白色字體三種顏色,那麼,有機會額外再自訂自己想要的顏色嗎?在 GitLab CI 的 script
是可以支援 ANSI 的色碼的,舉例來說:
job:
image: 'ubuntu:20.04'
script:
- echo -e "\e[31mThis text is red,\e[0m but this text isn't\e[31m however this text is red again."
上面的範例,即可以呈現紅白交替的字樣,如下:
其便是透過 ANSI 控制碼來進行字體顏色的設定,如 \e[31m
即是宣告後續的字體使用「紅色」,而 \e[0m
則是設定回原本的白色字樣,因此,如果有需要時常的使用紅色字體的話,也可以把字體的設定變為一個變數供整個 script 使用。如下(手冊上的範例):
job:
image: 'ubuntu:20.04'
before_script:
- TXT_RED="\e[31m" && TXT_CLEAR="\e[0m"
script:
- echo -e "${TXT_RED}This text is red,${TXT_CLEAR} but this part isn't${TXT_RED} however this part is again."
- echo "This text is not colored"
對應之執行結果:
如果有 Windows 及 Linux 同時使用的跨平台需求時,在使用控制碼改變顏色的時候要特別注意,在 bash
中控制顏色的方法與 Windows 裡頭 PowerShell 的控制的啟用方法是不太一樣的,如上面的案例,在 PowerShell 中必須做以下的修改:
job:
before_script:
- $esc="$([char]27)"; $TXT_RED="$esc[31m"; $TXT_CLEAR="$esc[0m"
script:
- Write-Host $TXT_RED"This text is red,"$TXT_CLEAR" but this text isn't"$TXT_RED" however this text is red again."
- Write-Host "This text is not colored"
最後,可以透過這個參考連結 ( bash:tip_colors_and_formatting - FLOZz' MISC ) 來找到需要的 ANSI color,像是閃爍、背景色等等的,都可以透過其中找到範例。
在這一篇中,主要有三個重點,在編輯 script 時,如果需要撰寫一些邏輯,可以則可以透過多行指令來編排,而如果有需要自訂錯誤讓工作停止時,可以透過 exit
非零的數值來自定錯誤,另外,在編寫多行文字時,相對的較容易發生語法問題,導致 YAML 無法執行,因此在正式 commit 前,可以透過 CI Lint 工具先做一次語法確認,如此可以減少等待時間。最後是 script 的小技巧,透過 ANSI 控制碼為 script 的輸出上色。
接下來,依然會繼續介紹關於 script 的其他細節;我是墨嗓(陳佑竹),期待這系列的文章能夠讓人有些幫助。