在上一篇的內容中,進行了兩種嘗試,但基於 GitLab 的特性,都無法滿足需求「依據特定階段工作執行狀態,來決定下一階段的工作為自動啟動或手動啟動」,接下來會繼續進行一些嘗試來滿足這個需求:
在上一個嘗試中由於無法在工作建立之前就決定好變數,因此無法使用 after_script
使用預載變數 CI_JOB_STATUS
的方法來建立變數讓下一個 Stage 根據該變數來決定該手動啟用或直接啟動,因此第二個嘗試決定改為採用 trigger 的模式,動態建立的 pipeline。到工作階段才來建立更新環境有關的 Pipeline 總可以吧?!
# cleanup.yml 實作子程序依據變數判斷是否要手動啟動
default:
image: ubuntu:20.04
cleanup job:
rules:
- if: $IS_MANUAL_START == "true"
when: manual
- when: always
before_script:
- echo "IS_MANUAL_START = $IS_MANUAL_START"
- if [[ $IS_MANUAL_START == "true" ]]; then echo 'is true'; fi;
- if [[ $IS_MANUAL_START != "true" ]]; then echo 'is false'; fi;
script:
- echo "run cleanup job"
接下來是 .gitlab-ci.yml
的實作:
# .gitlab-ci.yml
default:
image: ubuntu:24.04
stages:
- "teardown"
- "cleanup"
teardown job:
stage: teardown
variables:
IS_MANUAL_START: "false"
script:
- echo "run teardown job and exit 10"
#- exit 10
after_script:
- echo "in after script"
- if [[ $CI_JOB_STATUS == "failed" ]]; then IS_MANUAL_START="true"; fi;
- echo "IS_MANUAL_START=$IS_MANUAL_START"
- echo "IS_MANUAL_START=$IS_MANUAL_START" >> cleanup.env
allow_failure: true
artifacts:
reports:
dotenv: cleanup.env
cleanup trigger:
stage: cleanup
trigger:
include: cleanup.yml
forward:
yaml_variables: true
variables:
IS_MANUAL_START: $IS_MANUAL_START
這段 .gitlab-ci.yml
同樣是基於 CI_JOB_STATUS
變數的特性,可以在 after_script
中使用,用以帶入決定自訂變數 IS_MANUAL_START
數值,差別在於,這邊建立工作的方法是透過 trigger 建立 Child Pipeline。
這次的嘗試,結果是可行的。因為 Trigger Child Pipeline,的確有符合上一篇文章中提到的原則,是否要建立 Job 的 rule 必須在 Pipeline 建立前就決定。Trigger Pipeline 在建立 Child Pipeline 時就知道變數的狀態,因此符合。
不過這邊因為透過 after_script
中撰寫 if else
來控制變數,雖然是簡單的 if else 邏輯,但把控制 Pipeline 流程的 if else
放在 Job Script 裡頭,會導致 Pipeline 的邏輯相對的難以理解,是不是有更好的方案呢?
after_script:
- echo "in after script"
- if [[ $CI_JOB_STATUS == "failed" ]]; then IS_MANUAL_START="true"; fi;
when:on_success
及 when:on_failure
個別建立 Child Pipeline首先建立相關的 CI/CD YAML
# file name: cleanup_job_tmpl.yml
.cleanup_job_tmpl:
image: ubuntu:20.04
script:
- echo "run cleanup job"
# file name: cleanup_auto.yml
include: cleanup_job_tmpl.yml
cleanup_job_auto:
extends: .cleanup_job_tmpl
before_script:
- echo "auto run job"
# file name: cleanup_manual.yml
include: cleanup_job_tmpl.yml
cleanup_job_manual:
extends: .cleanup_job_tmpl
when: manual
before_script:
- echo "manual run job"
.gitlab-ci.yml
# file name: .gitlab-ci.yml
stages:
- "teardown"
- "cleanup"
default:
image: ubuntu:24.04
teardown job:
stage: teardown
script:
- echo "run teardown job and exit 10"
- exit 10
artifacts:
reports:
dotenv: cleanup.env
cleanup_auto_trigger:
stage: cleanup
when: on_success #(default on_success)
trigger:
include: cleanup_job_auto.yml
cleanup_manual_trigger:
stage: cleanup
when: on_failure
trigger:
include: cleanup_job_manual.yml
這個實驗結果,確認,也是可行的。如下圖,當把 exit 10
註解移除時,會發生錯誤,如下圖,會產出一個需要手動啟動的 Downstream Pipeline。
同樣的把 exit 10
移除後,則可以自動的啟動 Downstream Pipeline:
在 YAML 的工作條件中,直接使用 when
來依據上一段工作的成功與否定義預計要 trigger 的 child pipeline,可以發現,無論是建立自動啟動工作的 cleanup_auto_trigger
或是需要手動啟動工作的 cleanup_manual_trigger
關鍵點沒有邏輯判斷,都相對的更好讀一些,且直接在 Job 上描述啟動條件,相對容易理解,我個人認為,這個解決方案,應該會比第三個嘗試更好一些,正在讀這篇內容的你,覺得呢?有沒有更好的方案可以建議?
我是墨嗓(陳佑竹),期待這次的內容能帶給你實用的啟發與幫助。