使用 GitLab 的條件 CI/CD 流水線最佳化 DevSecOps 工作流程
CI/CD 流水線可以很簡單,也可以很複雜,但讓它們高效的是定義它們何時以及如何執行的規則。透過使用規則,您可以建立更智慧的 CI/CD 流水線,從而提高團隊生產力,並使組織能夠更快地迭代。在本指南中,您將瞭解不同型別的 CI/CD 流水線、它們的用例,以及如何透過利用規則來建立高效的 DevSecOps 工作流。
理解 GitLab 流水線
流水線是 GitLab 的 持續整合 和 持續交付/持續部署 框架中的頂級元件。它包含 作業,作業是待執行的任務列表。作業被組織到 階段 中,階段定義了作業的執行順序。
流水線可以具有 基本配置,其中作業在每個階段併發執行。流水線也可以具有複雜的設定,例如 父子流水線、合併佇列、多專案流水線,或者更高階的 有向無環圖 (DAG) 流水線。DAG 流水線是更高階的設定,用於處理複雜的依賴關係。
下圖是顯示作業依賴關係的 gitlab-runner 流水線 的表示。

下圖描繪了一個 DAG 流水線。

GitLab 流水線的複雜性通常由具體的用例決定。例如,一個用例可能需要測試應用程式並將其打包成容器;在這種情況下,GitLab 流水線甚至可以用於將容器部署到 Kubernetes 等編排器或容器登錄檔中。另一個用例可能涉及構建針對具有不同依賴關係的各種平臺的應用程式,這時我們的 DAG 流水線就大放異彩。
探索 CI/CD 規則
在 GitLab 中,CI/CD 規則是管理流水線中作業流程的關鍵。GitLab CI/CD 的強大功能之一是控制 CI/CD 作業何時執行的能力,這可以取決於上下文、所做的更改、工作流規則、CI/CD 變數的值或自定義條件。除了使用 rules,您還可以使用以下關鍵字來控制 CI/CD 流水線的流程:
needs:建立作業之間的關係,通常在 DAG 流水線中使用only:定義何時應執行作業except:定義何時不應執行作業workflow:控制何時建立流水線
注意: only 和 except 不應與 rules 一起使用,因為這可能導致意外行為。您將在後續章節中瞭解更多關於有效使用 rules 的資訊。
規則功能的簡介
rules 決定作業是否在流水線中執行以及何時執行。如果定義了多個 rules,它們將按順序進行評估,直到找到匹配的 rule,屆時將根據指定的配置執行作業。
rules 可以使用 if、changes、exists、allow_failure、needs 和 variables 關鍵字來定義。
rules:if
if 關鍵字會評估是否應將作業新增到流水線。評估基於作業或流水線作用域中定義的 CI/CD 變數 和 預定義 CI/CD 變數 的值。
job:
script:
- echo $(date)
rules:
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == $CI_DEFAULT_BRANCH
在上面的 CI/CD 指令碼中,作業使用 echo 命令列印當前日期和時間。僅當合並請求的源分支 (CI_MERGE_REQUEST_SOURCE_BRANCH_NAME) 與專案在 合併請求流水線 中的預設分支 (CI_DEFAULT_BRANCH) 相同時,才會執行該作業。您可以使用 == 和 != 運算子進行比較,而 =~ 和 !~ 運算子允許您將變數與正則表示式進行比較。您可以使用 && (AND) 和 || (OR) 運算子以及括號組合多個表示式。
rules:changes
使用 changes 關鍵字,您可以監視特定檔案或資料夾的更改,以執行作業。GitLab 使用 git 的 diffstat 的輸出來確定已更改的檔案,並將其與為 changes 規則提供的檔案陣列進行匹配。一個用例是基礎設施專案,它儲存了不同基礎設施元件的資原始檔,並且您希望在對 terraform 檔案進行更改時執行 terraform plan。
job:
script:
- terraform plan
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- terraform/**/*.tf
在此示例中,僅當 terraform 資料夾及其子目錄中的副檔名為 .tf 的檔案發生更改時,才會執行 terraform plan。附加規則可確保該作業在 合併請求流水線 中執行。
如下所示,changes 規則可以查詢使用 paths 對特定檔案的更改。
job:
script:
- terraform plan
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
paths:
- terraform/main.tf
還可以將源引用(分支、標籤、提交)中的檔案更改與 Git 儲存庫中的其他引用進行比較。CI/CD 作業僅在源引用與 rules:changes:compare_to 中定義的指定引用值不同時執行。此值可以是 Git 提交 SHA、標籤或分支名稱。以下示例將源引用與當前生產分支 refs/head/production 進行比較。
job:
script:
- terraform plan
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
paths:
- terraform/main.tf
compare_to: "refs/head/production"
rules:exists
與 changes 類似,您可以使用 rules:exists 規則僅在特定檔案存在時才執行 CI/CD 作業。例如,您可以執行一個檢查 Gemfile.lock 檔案是否存在。以下示例使用 bundler-audit 專案 來審計 Ruby 專案中是否存在易受攻擊的 gem 版本或不安全的 gem 源。
job:
script:
- bundle-audit check --format json --output bundle-audit.json
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
exists:
- Gemfile.lock
rules:allow_failure
在某些情況下,作業的失敗不應影響流水線中的後續作業和階段。這在需要將非阻塞任務作為專案的一部分但又不影響專案的用例中可能很有用。可以將 rules:allow_failure 規則設定為 true 或 false。當未指定規則時,它預設為 false。
job:
script:
- bundle-audit check --format json --output bundle-audit.json
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED == "false"
changes:
exists:
- Gemfile.lock
allow_failure: true
在此示例中,僅當合並請求事件觸發流水線且目標分支不受保護時,作業才可能失敗。
rules:needs
rules:needs 預設停用,它在 GitLab 16 中引入,並且可以使用 introduce_rules_with_needs 功能標誌 來啟用。needs 規則用於在不等待階段中其他作業完成的情況下按順序執行作業。當與 rules 一起使用時,如果滿足指定的條件,它將覆蓋作業的 needs 規範。
stages:
- build
- qa
- deploy
build-dev:
stage: build
rules:
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
script: echo "Building dev version..."
build-prod:
stage: build
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script: echo "Building production version..."
qa-checks:
stage: qa
script:
- echo "Running QA checks before publishing to Production...."
deploy:
stage: deploy
needs: ["build-dev"]
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
needs: ["build-prod", "qa-checks"]
- when: on_success # Run the job in other cases
script: echo "Deploying application."
在上面的示例中,deploy 作業在執行之前有一個 build-dev 作業作為依賴項;然而,當提交分支是專案的預設分支時,其依賴項將變為 build-prod 和 qa-checks。這允許根據上下文實現額外的檢查。
rules:variables
在某些情況下,您可能只需要在特定條件下才需要某些變數,或者它們的值可能會根據內容而變化。rules:variables 規則允許您在滿足特定條件時定義變數,從而實現更動態的 CI/CD 執行工作流。
job:
variables:
DEPLOY_VERSION: "dev"
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables:
DEPLOY_VERSION: "stable"
script:
- echo "Deploying $DEPLOY_VERSION version"
workflow:rules
到目前為止,我們已經瞭解瞭如何使用 rules 關鍵字來控制作業在流水線中執行的時間。有時,您想控制整個流水線的行為:這時 workflow:rules 提供了一個強大的選項。workflow:rules 在作業之前進行評估,並優先於作業規則。例如,如果一個作業的規則允許它在特定分支上執行,但是 workflow:rules 設定了在該分支上執行的作業的 when: never,那麼這些作業將不會執行。
前面各節中提到的 rules 的所有功能也適用於 workflow:rules。
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: $CI_PIPELINE_SOURCE == "push"
when: never
- when: always
在上面的示例中,CI/CD 流水線會執行,除非由計劃或推送事件觸發。
GitLab CI/CD 規則的實際應用
在上一個部分,我們探討了使用 GitLab CI/CD 的 rules 功能的各種方法。在本節中,讓我們探索一些實際用例。
開發者體驗
DevSecOps 平臺的優勢之一是它使開發人員能夠專注於他們最擅長的事情:編寫程式碼,同時最大限度地減少運維任務。公司的 DevOps 或平臺團隊可以為開發生命週期的各個階段建立 CI/CD 模板,並使用規則根據其技術棧新增 CI/CD 作業來處理特定任務。開發人員只需包含預設的 CI/CD 指令碼,流水線就會根據檢測到的檔案、使用的引用或定義的變數自動建立,從而提高生產力。
安全和質量保證
CI/CD 流水線的一個主要功能是在將錯誤或漏洞部署到生產環境之前捕獲它們。透過使用 CI/CD 規則,安全和質量保證團隊可以根據特定觸發器動態執行額外的檢查。例如,當檢測到未經批准的副檔名時,可以新增惡意軟體掃描;或者當代碼庫發生重大更改時,會自動新增更高階的效能測試。藉助 GitLab 內建的安全功能,只需幾行程式碼即可將安全整合到您的流水線中。
include:
# Static
- template: Jobs/Container-Scanning.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
- template: Jobs/SAST-IaC.gitlab-ci.yml
- template: Jobs/Code-Quality.gitlab-ci.yml
- template: Security/Coverage-Fuzzing.gitlab-ci.yml
# Dynamic
- template: Security/DAST.latest.gitlab-ci.yml
- template: Security/BAS.latest.gitlab-ci.yml
- template: Security/DAST-API.latest.gitlab-ci.yml
- template: API-Fuzzing.latest.gitlab-ci.yml
自動化
GitLab CI/CD 規則的強大之處在於其(幾乎)無限的自動化 CI/CD 流水線的可能性。GitLab AutoDevOps 就是一個例子。它使用一套有約束力的最佳實踐 GitLab CI/CD 模板 和規則來檢測使用的技術棧。AutoDevOps 會建立相關的作業,從推送開始,將您的應用程式一直交付到生產環境。您可以檢視 AutoDevOps 模板 以瞭解它如何利用 CI/CD 規則來提高效率。GitLab Duo 提供由 AI 驅動的工作流,有助於簡化任務並更快地構建安全軟體。
CI/CD 元件利用
隨著增長而來的是多次迭代和最佳實踐的建立。在構建 CI/CD 流水線時,您的 DevOps 團隊可能會建立多個 CI/CD 指令碼,並使用 include 關鍵字在流水線之間重複使用它們。透過 GitLab 16,GitLab 推出了 CI/CD 元件,這是一個實驗性功能,允許您的團隊建立可重用的 CI/CD 元件並將其釋出為目錄,以便快速構建更智慧的 CI/CD 流水線。您可以瞭解更多關於 使用 CI/CD 元件 和 元件目錄方向 的資訊。
總結
在本指南中,我們探討了 GitLab CI/CD 流水線的不同型別,從理解其基本結構到增強 DevSecOps 工作流的高階配置。GitLab CI/CD 使您能夠利用規則來執行更智慧的流水線。它與 GitLab Duo 的 AI 驅動的工作流一起,幫助您快速構建安全軟體。我們鼓勵您利用這些強大的功能來最佳化您的 DevSecOps 計劃。
這是一篇 GitLab 的贊助文章。GitLab 是一個全面的基於 Web 的 DevSecOps 平臺,提供 Git 儲存庫管理、問題跟蹤、持續整合和部署流水線功能。它提供開源和專有版本,旨在覆蓋整個 DevOps 生命週期,是團隊尋求單一平臺來管理程式碼和操作資料的熱門選擇。