iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
IT Operation

寫完微服務然後呢?走向平台工程的黃金路徑系列 第 14 篇

Day 14 - 用 GitHub Actions 建立 CI 工作流程

  • 分享至 

  • xImage
  •  

CI/CD 簡介

平台工程不只要提供 Kubernetes、GitOps 或觀測工具,也要讓團隊知道程式碼改完後怎麼往下走:誰來確認它能編譯、測試有沒有通過、Container Image 從哪個 commit 建出來,又該由誰決定它何時進入環境?這些問題構成了持續整合與持續交付(Continuous Integration/Continuous Delivery,CI/CD)的工作。

CI 會在每次變更時重複執行 restore、test 與 build,及早找出不能合併的原始碼;CD 則依環境規則,將已核准的 Container Image 部署到指定環境。兩者不必由同一個工具或 job 完成,但交接要清楚:CI 留下能回查來源的檢查結果,CD 再決定要部署哪個版本。

這篇先用 GitHub Actions 建立 Todo 服務的 CI 檢查。GitOps 負責將 Git 中已核准的環境設定收斂到叢集;它不判斷原始碼能否編譯,也不執行測試。因此,每次 Pull Request(PR)變更服務時,CI 都要留下可重複執行的檢查結果。

CI 只驗證來源,不直接部署

CI 與 CD 常被放在同一條 pipeline,但它們處理的問題和需要的權限不同:

階段 要回答的問題 不該擁有的權限
CI 這份原始碼能 restore、test、build 嗎?產物來自哪個 commit? Production Kubernetes 寫入權限
GitOps CD 已核准的設定是否應收斂到目標環境?資源是否健康? 任意修改 application source 的權限

這個界線要先切清楚。CI 可以建置 Container Image,也可以建立更新 GitOps 設定的 PR;但它不需要拿著 kubeconfig 對 Production 執行 kubectl apply。把叢集寫入權留給叢集內受限的 GitOps controller,才能讓原始碼驗證和環境部署各自留下可追查的責任邊界。

先從 Todo 服務目前能執行的檢查開始

目前的 Todo 範例有兩個 .NET 8 專案:Todo.Api 提供待辦事項 API,Todo.Bff 轉送瀏覽器送進來的 API 請求。兩個專案各自有 .csproj 與 Dockerfile,沒有 solution 檔,也尚未建立 unit test project。

因此,PR 檢查不應假裝已經涵蓋不存在的測試。現階段 workflow 仍執行 dotnet test,讓每個專案都走過相同的 test 入口;但沒有測試專案時,這一步不會驗證任何 unit test。真正補上測試後,CI 才能把測試失敗留在 PR,而不是等到 image 或叢集裡才發現問題。

pull request
  │
  ├── restore:取得指定專案的 NuGet 相依套件
  ├── test:執行專案的測試入口
  ├── build:以 Release 設定編譯
  └── 回饋:將失敗留在 PR

用專案矩陣執行相同的檢查

workflow 將 Todo.Api 和 Todo.Bff 放進 matrix。兩個 job 都使用相同的 .NET SDK、restore、test 與 build 步驟;其中一個失敗時,另一個仍會繼續執行,PR 可以一次看到兩個專案的結果。

name: todo-ci

on:
  pull_request:
    paths:
      - "src/0-todo-microservices/**"
      - ".github/workflows/todo-ci.yaml"

permissions:
  contents: read

jobs:
  validate:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        project:
          - src/0-todo-microservices/Todo.Api/Todo.Api.csproj
          - src/0-todo-microservices/Todo.Bff/Todo.Bff.csproj
    steps:
      - name: Check out source
        uses: actions/checkout@v4

      - name: Set up .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: 8.0.x

      - name: Restore NuGet packages
        run: dotnet restore ${{ matrix.project }}

      - name: Run tests
        run: dotnet test ${{ matrix.project }} --configuration Release --no-restore

      - name: Build release artifacts
        run: dotnet build ${{ matrix.project }} --configuration Release --no-restore

permissions 只給 contents: read,因此 workflow 可以讀取 repository,卻不能推送 image、寫入 GitOps 設定或操作 Kubernetes。後續需要發佈 image 的 job 應另行設定最小權限,不能因為 PR workflow 曾經需要讀取原始碼,就順手加上 packages: write 或 Kubernetes credential。

fail-fast: false 的作用是保留兩個專案的檢查結果,不是忽略失敗。只要任一 matrix job 失敗,整個 workflow 仍會失敗;PR 不會因此取得可合併的綠燈。

目前 repository 沒有 packages.lock.json,所以這個 workflow 沒有啟用 actions/setup-dotnet 的 NuGet cache。採用 lock file 後,才能以 lock file 作為 cache key,避免相同 commit 因為相依套件解析不同而得到不一致的結果。不能只開啟 cache,就把它當成相依版本可重現的保證。

綠燈涵蓋的範圍有限

CI 成功只表示指定的 checks 已通過,不能延伸成所有風險都已排除:

  • 現在沒有 unit test project,dotnet test 成功不代表功能已被測試。
  • build 成功不代表 Container Image 沒有已知漏洞或不安全設定。
  • CI 不會驗證 migration 能否和舊版服務相容。
  • CI 不會證明 Staging 或 Production 的外部依賴與本機相同。

CI 先把原始碼層能立即發現的問題擋在前面。部署後的觀測資料與資源 Policy 分別處理問題調查和資源規則;它們不會因為 CI 綠燈就失去必要性。

在本機重現 PR 檢查

GitHub Actions 的 runner 會執行下列命令。送出 PR 前可在 repository root 執行同一組指令:

dotnet restore src/0-todo-microservices/Todo.Api/Todo.Api.csproj
dotnet test src/0-todo-microservices/Todo.Api/Todo.Api.csproj --configuration Release --no-restore
dotnet build src/0-todo-microservices/Todo.Api/Todo.Api.csproj --configuration Release --no-restore

dotnet restore src/0-todo-microservices/Todo.Bff/Todo.Bff.csproj
dotnet test src/0-todo-microservices/Todo.Bff/Todo.Bff.csproj --configuration Release --no-restore
dotnet build src/0-todo-microservices/Todo.Bff/Todo.Bff.csproj --configuration Release --no-restore

驗收時,刻意讓其中一個專案無法編譯,確認對應 matrix job 顯示 compiler error,且 workflow 整體失敗。建立 unit test project 後,也應刻意讓一個測試失敗,確認 job 停在 test 步驟而不會把未驗證的程式碼當成可交付產物。

下一篇會將通過檢查的服務封裝成 Container Image,並釐清 release tag、Git SHA 與 immutable digest 分別適合處理什麼問題。


上一篇
Day 13 - 在 Grafana 查看 Prometheus、Loki 與 Trace 資料
下一篇
Day 15 - 在 CI 建置 Docker Image,並管理 Tag
系列文
寫完微服務然後呢?走向平台工程的黃金路徑 共 15 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言