iT邦幫忙

2025 iThome 鐵人賽

DAY 29
1

這一篇的內容,回到基礎的 GitLab CI/CD YAML 語法,這次要談關於 CI/CD YAML 的 workflowworkflow 這個語法主要在控制整個 Pipeline 的行為,可以控制的部分分為三種類型,分別是:基本控制、條件控制以及自動取消條件三種。

workflow 的基本控制

一般情況下,在 Pipelines 的列表下,其 Pipeline 的名稱會以當下的 commit message 來呈現,但有時候為了好分辨 Pipeline 來自什麼分支或 Pipeline 的功能,可能會需要讓 Pipeline 有一個好識別的名稱,這時候就可以使用 workflow:name

以底下第一個範例:

workflow:
  name: 'Pipeline for branch: $CI_COMMIT_BRANCH'

當建立 Pipeline 之後,如此次的範例分支 day29_01_workflow_name,在列表上會呈現 Pipeline for branch: day29_01_workf...。如下圖上方的 Pipeline。

https://ithelp.ithome.com.tw/upload/images/20251008/20072606ZM5crXhq0M.png

而稍微複雜一點的案例甚至可以依據後續會介紹的 workflow:rulesrules 中設定變數,並且在 workflow:name 中使用該變數,如此設定,pipeline 就可以依據不一樣的條件有不一樣的名稱。如 GitLab 官方手冊上的範例:

variables:
  PROJECT1_PIPELINE_NAME: 'Default pipeline name'  # A default is not required

workflow:
  name: '$PROJECT1_PIPELINE_NAME'
  rules:
    - if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby3/'
      variables:
        PROJECT1_PIPELINE_NAME: 'Ruby 3 pipeline'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      variables:
        PROJECT1_PIPELINE_NAME: 'MR pipeline: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME'
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  # For default branch pipelines, use the default name

workflow:name 使用變數 $PROJECT1_PIPELINE_NAME 變數數值為什麼,Pipeline 名稱就是什麼。因此當 rules 的條件成立時,設定好變數,則 Pipeline 的名稱就會是什麼。 值得注意的,當變數名稱為空字串時,GitLab 會預設呈現預設值,最後一個 commit 的訊息名稱。

workflow:rules 條件控制

CI/CD YAML 的 workflow:rules 其使用的方法與之前介紹的 Job 層級的 rules 是類似的,可以使用 ifchangesexistsvariableswhen 這些關鍵字。不過 when 目前只支援 alwaysnever

CI/CD YAML 的 workflow:rules:variables 語法,與 rules:variables 是一樣的,當 rules 條件成立時,則建立該對應的變數,不過這邊定義的變數,可以供 Pipeline 中的所有 Job 使用。另外,在定義變數時,也可以使用 GitLab 提供的 Pre-Defined 變數,但要注意,無法使用需要在 Job 建立之後才存在的變數,如之前使用過的 CI_JOB_ID

workflow:rules:auto_cancel 可以與後面要介紹的 workflow:auto_cancel 搭配,當特定條件下,自動取消的動作與預設自動取消的行為不同時,可以透過 workflow:rules:auto_cancel 重新複寫自動取消的宣告。其同樣支援 on_job_failure 當發生錯誤時及 on_new_commit 當 branch 有新的 commit 時,這兩個數值。

如 GitLab 官方手冊上的範例:

workflow:
  auto_cancel:
    on_new_commit: interruptible
    on_job_failure: all
  rules:
    - if: $CI_COMMIT_REF_PROTECTED == 'true'
      auto_cancel:
        on_new_commit: none
        on_job_failure: none
    - when: always                  # Run the pipeline in other cases

test-job1:
  script: sleep 10
  interruptible: false

test-job2:
  script: sleep 10
  interruptible: true

在範例中為整個 Pipeline 設定預設值:

  • workflow:auto_cancel:on_new_commit 設定為 interruptible
  • workflow:auto_cancel:on_job_failure 設定為 all
    但,如果 CI_COMMIT_REF_PROTECTED變數為 true 時則覆寫上面設定的預設值,變為:
  • on_new_commitnone
  • on_job_failurenone
    如此,當 Pipeline 作用時,如果發生在:
  • 當非保護的分支 (non-protected),啟動後,有新的 commit 推送,則 test-job1 會繼續執行,但 test-job2 會自動取消。
  • 當在保護的分支啟動後,有新的 commit 推送,則test-job1test-job2 都會繼續執行。

workflow:auto_cancel 自動取消條件

auto_cancel 目前支援 on_new_commiton_job_failure 其中,on_new_commit 支援以下數值:

  • interruptible:中斷有標注 interruptibletrue 的 Job。
  • none:不自動停止任何 Job。
  • conservative:在沒有任何 interruptiblefalse 的 Job 啟動前,停止整個 Pipeline。未設定時的預設值。

workflow:auto_cancel:on_new_commit

workflow:
  auto_cancel:
    on_new_commit: interruptible

job1:
  interruptible: true
  script: sleep 60

job2:
  interruptible: false  # Default when not defined.
  script: sleep 60

如上面的範例:

  • 當新的 commit 推送到分支時,GitLab 會建立一個新的管道,並建立 job1job2兩個 Job。
  • 但,如果在 Job 完成前,又有新的 commit 推送,則依據設定只有 job1 會被取消。

workflow:auto_cancel:on_job_failure

on_job_failure 適用於當 Pipeline 執行的過程中,有 Job 失敗時對整個 Pipeline 的處置條件,支援以下兩個數值:

  • all:一旦有 Job 失敗,立即取消 Pipeline 及所有正在執行的 Job。
  • none:不自動取消任何 Job。
stages: [stage_a, stage_b]

workflow:
  auto_cancel:
    on_job_failure: all

job1:
  stage: stage_a
  script: sleep 60

job2:
  stage: stage_a
  script:
    - sleep 30
    - exit 1

job3:
  stage: stage_b
  script:
    - sleep 30

如上面的範例,執行的過程中 job2 刻意 exit 1 造成 job 失敗,則如果 job1還在執行中,將會被取消,且 job3 將不會啟動。

總結

GitLab CI/CD YAML 的 workflow 主要是針對 Pipeline 相對全局性的控制,有些特性與 Job 底下的特性是一致的,像是 rulesvariables 的部分,而相對比較不一樣的是 auto_cancel 的部分,這邊的特性對於一些場景,如「只要該分支上最終的成果」 ,則就可以考慮使用 on_new_commit的特性,因為只要最後的結果,所以前面的 Job 就變得不重要,甚至多執行都是資源的浪費。

同樣的,當 Pipeline 上,任何一個 job 發生錯誤,就代表整個 Pipeline 有錯誤時,就可以考慮使用 on_job_failure 的特性,直接取消整個 Pipeline 的工作。因為有錯誤,所以其他的 job 有沒有成功就變得不重要。

我是墨嗓(陳佑竹),期待這次的內容能帶給你實用的啟發與幫助。

參考範例

參考連結


上一篇
Day28 - GitLab Runner 的自動擴展 (以 Google Cloud Platform GCP為例) - 3
系列文
GitLab CI 2025:深入玩轉流水線與實戰紀錄29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言