iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 10
0
DevOps

用 GitLab CI 玩轉自動化測試與佈署系列 第 10

Day10 - GitLab CI 流水線上的每個工作都要執行嗎?三談工作執行的條件設定

在前面的兩篇提到了 whenonlyexcept 來設定工作的執行條件,在這一篇裡,將要提到 rules 這個在 GitLab 12.3 之後提供的條件設定功能。這是一個可以說結合了 whenonlyexcept 三者功能的參數,那麼它可以做些什麼呢?

GitLab CI 提供的 rules 可以作些什麼?

rules 參數裡,可以搭配 whenallow_failureifchangesexists 等等的參數,舉手冊上的例子來說:

docker build:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - if: '$CI_COMMIT_BRANCH == "master"'
      when: delayed
      start_in: '3 hours'
      allow_failure: true

這個範例提供了「如果 GIT commit 的分支為 master 時,那就在 3 小時之後執行這個工作,且允許執行失敗」。可以發現,寫 rules 的條件判斷,相對使用 whenonlyexcept 多了一些「邏輯感」,因此,我個人在使用上如遇到比較複雜的條件時,我會傾向使用 rules 來完成。但必須注意,「不能」把 rulesonlyexcept同時使用,且就算透過 CI Lint 檢測語法,可能也不會顯示錯誤。

細談 rules 的參數

目前 rules 主要提供了三個參數:

  • if:透過 if 這個參數可以設定或排除某些條件,其功能與 only:variables 提供的相似。
  • changes:當 GIT Commit 的檔案內容包含設定的檔案變更時執行,其效果與 only:changes 的功能相似。
  • exist:當 GIT Commit 裡的檔案存在某些檔案時執行。

在同一個 rules 裡頭,條件之間是以「且 AND」的型態呈現,但參數裡頭則是以「或 OR」的型態描述,舉底下的例子來說:

build:docker:
  script:
    - echo 'build docker image'
  rules:
    - if: '$VAR == "string value"'
      changes:
        - Dockerfile
        - docker/scripts/*
      when: manual

上面的例子成立的條件是:

  1. 當變數 $VAR 的內容為 “string value”
  2. 變更的檔案包含 Dockerfiledocker/scripts/* 資料夾底下的檔案。
  3. 當手動觸發此工作時

另外 rules:if 自 GitLab 13.3 開始,條件還可以搭配括弧(Parentheses)來描述,如官方手冊的範例,透過括弧可以搭配出更「多元」的條件:

job1:
  script:
    - echo This rule uses parentheses.
  rules:
    if: ($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE

細談 rules 下的 allow_failure

另外,如果在 jobrules 中都使用了 allow_failure,則 rules 階層的 allow_failure 可以覆寫掉 job 階層的。如底下的範例,當 if 條件成立時,則 allow_failuretrue

job:
  script: "echo Hello, Rules!"
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      when: manual
      allow_failure: true

rules 的條件流程

GitLab CI 的 rules 可以同時設定多個條件式,其聯合在一起的效果就如邏輯判斷中的「if...elseif...elseif...」類似,因此,使用上也必須要注意,當其中一個「條件」成立了,則該工作以這個條件設定的內容為主。

job:
  script: "echo Hello, Rules!"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: manual
      allow_failure: true
    - if: '$CI_PIPELINE_SOURCE == "schedule"'

以上面的這個例子來說,總共有兩個條件式,其一是「當流水線的啟動來自 Merge 請求,且手動觸發時,則允許這個工作失敗」,其二「當流水線的啟動來自排程」,這代表著,當成立條件為第一項時「允許工作失敗」,當成立條件為第二項時,則「不允許」工作失敗(allow_failure: false 為預設值),當兩個條件都不成立時,則這個工作不執行。

那麼,如果要設定反向邏輯呢?如手冊上提出的範例:

job:
  script: "echo Hello, Rules!"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: never
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
      when: never
    - when: on_success

條件是如下:

  • 條件一:流水線啟動來自 Merge 請求,則不執行
  • 條件二:流水線啟動來自排程,則不執行
  • 條件三:前一關卡成功時執行
    上面這範例就可以說:「這個工作除了流水線請求來自『Merge 請求』及 『排程』不執行外,只要前一關卡成功都執行」。

總結:

rules 的使用裡,我們可以透過更豐富多元的條件來設定工作該不該作,但也必須要特別注意這些條件是否能真正描述到想要達成的條件,另外也要特別注意條件成立時內額外設定的參數,是否是預期的。

接下來要繼續談工作與工作之間的互動。我是墨嗓(陳佑竹),期待這系列的文章能夠讓人有些幫助。


上一篇
Day09 - GitLab CI 流水線上的每個工作都要執行嗎?再談工作執行條件設定
下一篇
Day11 - GitLab CI 工作與工作間的關聯與互動?談有向無環圖與 needs 參數
系列文
用 GitLab CI 玩轉自動化測試與佈署31

尚未有邦友留言

立即登入留言