上一篇提到了在 .gitlab-ci.yml
中使用 when
來定義依據前一關卡的執行結果執行這個工作,但 when
這個屬性只能根據之前的關卡來設定什麼時候開始只行,如果是要依據此次 Git 上的一些特徵來執行,該怎麼處理呢?
only
及 except
來根據 Git Repo 的內容執行在 .gitlab-ci.yml
中可以透過 only
及 except
兩個來設定,目前的這個工作「只在」或「不在」什麼條件下執行,且這兩個參數,都可以使用一些特別的關鍵字,如目前 GitLab 官方手冊上所說,可以使用的關鍵字如下:
關鍵字 | 描述 |
---|---|
api |
透過 pipelines API 啟動 |
branches |
當目前啟動啟用流水線的 Git Reference 是一個 Git 分支時 |
chat |
當流水線是透過 GitLab ChatOps 的指令啟動時 |
external |
當使用的是外部的持續整合(CI)服務時(此法目前尚未找到範例,尚不知如何判斷是外部 CI 服務) |
external_pull_requests |
當從外部發起 Pull Request 的時候。(細部說明可自官方手冊查看). |
merge_requests |
只在合併請求 (merge request) 建立或更新時。細部功能可查看。手冊中 merge request pipelines、merged results pipelines 及 merge trains 三個頁面。 |
pipelines |
使用在 multi-project pipelines 透過 API 搭配 CI_JOB_TOKEN 或 trigger 觸發關鍵字建立。 |
pushes |
當 Pipeline 是透過 git push 事件所觸發而建立的時候。 |
schedules |
當為設定之排程而啟用的流水線 Pipelines. |
tags |
當目前啟動啟用流水線的 Git Reference 是一個 tag 時。 |
triggers |
當流水線是透過 trigger token 啟動時。 |
web |
當流水線是透過 Web 介面上「run pipeline」所啟動執行時。 |
在這邊,以 only
舉例來說:
job:
only:
- tags
- triggers
- schedules
上面的這個例子,這個工作,就只會發生在目前工作流程流水線使用的 Git Reference 上有 tags
「或」透過 trigger 觸發時或透過排程啟動時才會執行這個工作。
反之,如果是 except
則剛好相反,當 Git Reference 上有 tags
或 透過 trigger 觸發時或透過排程啟動時才會執行這個工作,「都不執行」這個工作。
job:
except:
- tags
- triggers
- schedules
另外,除了關鍵字的使用,一般的使用上也可以針對 Git Reference 作字串的比較,目前支援 RE2 作為進階的字串比較(正規表示式 regexp 在 GitLab 11.9.4 之後停止支援),當符合條件時,執行這個工作,舉官方手冊上的例子來說:
job:
only:
- /^issue-.*$/
上面的這個例子,透過 RE2 的分析後,這個工作,就只會在 Git Reference 符合 issue-
開頭的時候執行。這特性也適合用在特定分支名稱才執行某些工作的場景,像是 feature 分支才需要進行原始碼格式檢查之類的工作。
另外,也可以透過 RE2 的 i 標籤來做字母大小寫同時比對,舉例來說:
job:
only:
- /^issue-.*$/i
上面的這個例子,不管是 git 分支名稱 ISSUE-
或 Issue-
開頭,均會執行。
only
與 except
是否可以同時存在?在 GitLab CI 的設計中 only
與 except
是可以一起使用的。但是必須要注意兩者均不存在交集的情境,當發生 only
與 except
不存在交集的情境時,則該工作會永遠被跳過。以底下的例子:
default:
image: ubuntu:20.04
build:
stage: build
script:
- echo "BUILD_VERSION=hello" >> variable.env
- echo "BUILD_NAME=GitLab" >> variable.env
deploy:
stage: deploy
script:
- echo 'do deploy process'
only:
- /^master/i
except:
- branches
上面的這個例子流水線案例,執行在 master
分支上,而 deploy
這個工作,因為在 only
中使用了 RE2 描述 /^master/i
代表 Git Reference 名稱不分大小寫符合 master 開頭的均執行,而 except
的部分,描述了只要 Git Reference 是一個分支,就「不」執行,兩個條件在 master 上均成立,因此最終 deploy
的工作直接跳過不執行。
only
與 except
在 GitLab CI 的設計裡 only
與 except
還可以進行更複雜的進階使用,但截至目前的 13.3 版本,都還是將這些功能都還是 alpha
階段,未來可能會移除或調整,因此在使用上要特別注意。
在進階使用裡頭,額外支援四個關鍵字:
refs
:分之名稱variables
:變數對應之字串是否符合changes
:檔案如有變更kubernetes
:專案中的 kubernetes 服務是否啟動這四個關鍵字,在 only
的使用上,彼此之間是以「 AND 並且」的條件來執行的,必須都有通過才會執行,以官方手冊上面的這個例子:
test:
script: npm run test
only:
refs:
- master
- schedules
variables:
- $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/
kubernetes: active
上面的例子表示,這個工作只有在底下的三個條件「均成立」才會執行:
但在 except
的使用上則是「OR 或」的條件來執行,只要其中一個條件符合,則該工作就「不」執行。同樣以官方手冊上的範例:
test:
script: npm run test
except:
refs:
- master
changes:
- "README.md"
上面的例子,當底下的這兩個條件,只要其中一個成立,都「不」執行:
在上面的例子中,可以透過 changes
這個參數來判斷哪些檔案變更,才執行或不執行什麼工作。則如果一個專案同時置放了前端與後端的原始碼,且前後端都有對應的單元測試程式,那麼就可以透過這特性,讓前端或後端的測試,僅執行在前後端對應的原始碼有變更的時候。如底下的範例,該這個 front_test
工作,僅會在對應的資料夾下有檔案變更時才進行工作 :
front_test:
script:
- echo 'front test'
only:
changes:
- front/src/*
- front/tests/*
如兩個執行結果,其一,因為新增了 front/src
及 front/tests
底下的檔案,則front_test
有執行。
其二,因為僅變更根目錄下的 README.md
檔案,則 front_test
不執行。
在 only
與 except
的使用上要特別注意是否預想的條件如設計中的成立,實務使用上,會遇到 RE2 撰寫的規則實際執行後不如自己所想的,可以透過一些線上工具先做過測試確認。
關於 GitLab CI 上的條件執行,還有 rules
尚未介紹到,會出現在下一篇。我是墨嗓(陳佑竹),期待這系列的文章能夠讓人有些幫助。