上一篇談到 needs 如果需要 Parent Pipeline 的 Artifact 時,可以透過 needs:pipeline:job
搭配 Parent Pipeline 觸發 Child Pipeline 時帶入 Pipeline Id來讓 Child Pipeline 的 Job 可以取得 Artifact,而這一篇要繼續談 needs 另外的特性。
在流水線的設計上,在不同的情境或執行環境下,有些 Job 可以不用執行,或特殊的 Job 只在特定的環境下才執行,但又會設計當有執行時,後續的 Job 需要這些 Job 通過後才能執行。
舉例來說,當有一個流水線,包含兩種測試,分別是單元測試(unit test)及整合測試(integration test),整合測試希望只在特定分支執行(如主分支),在其他的開發分支只執行單元測試。而如果後續有一個部署的工作,一般會需要單元測試及整合測試都通過了,才執行部署工作,以往這邊就會設計為 needs: [unit_test, integration_test]
,但,這樣的設定,在不執行整合測試的分支,就會導致觸發流水線時,直接產出無法建立 Pipeline 的錯誤訊息。
Unable to create pipeline
'deploy' job needs 'integration_test' job, but 'integration_test' does not exist in the pipeline. This might be because of the only, except, or rules keywords. To need a job that sometimes does not exist in the pipeline, use needs:optional.
那這樣的場景下,應該怎麼處理呢? 這時候可以使用 needs
系列的 needs:optional
,它可以設定 needs
的工作,在存在的時候才需要。以上面提到的案例來說,可以這樣使用:
default:
image: ubuntu:24.04
stages:
- test
- deploy
unit_test:
stage: test
script:
- echo "Running unit tests..."
- sleep 3
- echo "Unit tests done!"
integration_test:
stage: test
script:
- echo "Running integration tests..."
- sleep 5
- echo "Integration tests done!"
rules:
- if: '$CI_COMMIT_BRANCH == "main"' # 只在 main 分支才執行
- when: never
deploy:
stage: deploy
script:
- echo "Deploying application..."
needs:
- job: unit_test
- job: integration_test
optional: true
這邊最重要的設定是 deploy
中作中的 needs
設定,當 integration_test
存在的時候,才被納入 needs
中:
needs:
- job: unit_test
- job: integration_test
optional: true
在使用 needs:optional
的時候,依然有一些使用上的規則與限制:
needs
只設定一個 job,且這個 job 設定 optional: true
,但該 job 又在該情境下不執行,則其會等同 needs: []
的效果。needs:optional
為 false。所以當所需要的 job 不存在,則與過去的案例一樣,會產生無法建立 Pipeline 的錯誤訊息。這篇介紹了 needs:optional
的用途,特別適合處理某些 只在特定情境才執行的工作。像是單元測試永遠要跑,但整合測試只在主分支才執行,若部署工作同時需要依賴兩者,就可能遇到「Job 不存在導致 Pipeline 無法建立」的問題。透過 needs:optional
,可以讓部署在有整合測試時等待它完成,沒有時則自動忽略,讓流水線設計更彈性與穩定。我是墨嗓(陳佑竹),期待這次的內容能帶給你實用的啟發與幫助。