本文 AI 產出,尚未審核

Golang 專案實戰與部署:CI/CD 管道(GitHub Actions、GitLab CI)

簡介

在現代軟體開發流程中,**持續整合(CI)持續部署(CD)**已成為提升開發效率、降低錯誤率的關鍵手段。對於 Golang 專案而言,透過自動化的測試、建置與發佈流程,不僅可以確保每一次程式碼變更都能順利通過測試,還能在短時間內將新版本部署到生產環境或容器平台。

本篇文章將以 GitHub ActionsGitLab CI 為例,說明如何為 Golang 專案建立完整的 CI/CD 管道。從概念說明、實作範例,到常見陷阱與最佳實踐,提供初學者到中階開發者都能直接套用的步驟與技巧。


核心概念

1. CI/CD 的基本流程

步驟 說明
觸發 透過 pushmerge requesttag 等事件啟動 pipeline。
檢查 拉取程式碼、安裝相依套件。
測試 執行單元測試、整合測試,確保功能正確。
建置 編譯二進位檔、產生 Docker 映像。
部署 推送映像至容器註冊表、或直接部署至 Kubernetes / VM。
回報 產生報告、通知開發者(如 Slack、Email)。

重點:CI 主要關注「測試」與「建置」,CD 則延伸到「自動部署」與「回饋」。

2. 為什麼選擇 GitHub Actions / GitLab CI?

平台 優點
GitHub Actions - 原生整合於 GitHub,設定檔即存於 repo。
- 社群豐富的 Marketplace Action。
- 支援矩陣測試 (matrix) 與自訂執行環境。
GitLab CI - 完整的 DevOps 套件(CI、CD、容器註冊表、監控)。
- 可在自建 GitLab 伺服器上運行,適合企業內部。
- 支援 rulesneeds 等進階排程。

兩者的概念相同,語法略有差異,以下分別示範。

3. Golang 專案的 CI 要點

  1. 使用 Go Modulesgo.mod / go.sum 必須在 CI 中正確下載相依套件。
  2. 測試覆蓋率:建議在 CI 中產生 coverage.out,並上傳至 Codecov 或 GitHub Actions 的報告。
  3. 跨平台建置:若要產出 Linux、Windows、macOS 的二進位檔,可利用矩陣測試。
  4. Docker 映像:最終部署往往以 Docker 為單位,建置 Dockerfile 並推送至容器註冊表。

程式碼範例

以下示範三個常見的 CI/CD 任務:測試與覆蓋率跨平台建置Docker 映像推送。每個範例皆包含完整說明,您只需要將檔案放入專案根目錄即可。

3.1 GitHub Actions:基本測試與覆蓋率

.github/workflows/go-test.yml

name: Go CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      # 1️⃣ Checkout 程式碼
      - uses: actions/checkout@v4

      # 2️⃣ 設定 Go 環境
      - name: Set up Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.22'   # 依需求調整

      # 3️⃣ 快取相依套件 (加速後續執行)
      - name: Cache Go modules
        uses: actions/cache@v3
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-

      # 4️⃣ 下載相依套件
      - name: Install dependencies
        run: go mod download

      # 5️⃣ 執行測試並產生 coverage
      - name: Run tests
        run: |
          go test ./... -coverprofile=coverage.out -covermode=atomic
          go tool cover -func=coverage.out

      # 6️⃣ 上傳 coverage 給 Codecov(可自行選擇其他服務)
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: coverage.out
          token: ${{ secrets.CODECOV_TOKEN }}

說明

  • actions/cache 能顯著降低 go mod download 的時間。
  • go test ./... 會遞迴測試所有子目錄。
  • 若專案使用私有套件,請在 settings > Secrets 中設定 GOPRIVATESSH 金鑰。

3.2 GitHub Actions:跨平台建置二進位檔

.github/workflows/go-build.yml

name: Build Binaries

on:
  release:
    types: [created]   # 只在新發佈的 tag 時觸發

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        arch: [amd64, arm64]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.22'

      - name: Build
        env:
          GOOS: ${{ matrix.os == 'windows-latest' && 'windows' || matrix.os == 'macos-latest' && 'darwin' || 'linux' }}
          GOARCH: ${{ matrix.arch }}
        run: |
          mkdir -p dist
          go build -ldflags="-s -w" -o dist/myapp-${GOOS}-${GOARCH}${{ matrix.os == 'windows-latest' && '.exe' || '' }} ./cmd/myapp

      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: myapp-${{ matrix.os }}-${{ matrix.arch }}
          path: dist/*

說明

  • 使用 matrix 同時在三個作業系統、兩個 CPU 架構上建置,省去手動建立多個 workflow。
  • GOOSGOARCH 透過環境變數控制,-ldflags="-s -w" 可減小二進位檔大小。
  • upload-artifact 讓建置產物在 GitHub UI 可直接下載,或在後續的 Deploy 步驟中使用。

3.3 GitLab CI:完整 CI/CD(測試 → Docker → 推送)

.gitlab-ci.yml

image: golang:1.22

variables:
  # Docker 相關變數
  DOCKER_REGISTRY: registry.gitlab.com
  IMAGE_NAME: $DOCKER_REGISTRY/$CI_PROJECT_PATH/myapp
  # 設定 Go modules 快取
  GOMODCACHE: $CI_PROJECT_DIR/.cache/go-mod

stages:
  - test
  - build
  - deploy

# ------------------------------
# 1️⃣ Test stage
# ------------------------------
test:
  stage: test
  cache:
    key: "${CI_COMMIT_REF_SLUG}"
    paths:
      - .cache/go-mod
  script:
    - go mod download
    - go test ./... -coverprofile=coverage.out -covermode=atomic
  artifacts:
    reports:
      cobertura: coverage.out
    expire_in: 1 week

# ------------------------------
# 2️⃣ Build Docker image
# ------------------------------
docker-build:
  stage: build
  needs: [test]
  services:
    - docker:dind
  image: docker:latest
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $DOCKER_REGISTRY
    - docker build -t $IMAGE_NAME:$CI_COMMIT_SHORT_SHA .
    - docker tag $IMAGE_NAME:$CI_COMMIT_SHORT_SHA $IMAGE_NAME:latest
    - docker push $IMAGE_NAME:$CI_COMMIT_SHORT_SHA
    - docker push $IMAGE_NAME:latest
  only:
    - main
    - tags

# ------------------------------
# 3️⃣ Deploy to Kubernetes (optional)
# ------------------------------
deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config set-cluster k8s --server=$KUBE_SERVER --certificate-authority=$KUBE_CA
    - kubectl config set-credentials deploy --token=$KUBE_TOKEN
    - kubectl config set-context default --cluster=k8s --user=deploy --namespace=production
    - kubectl config use-context default
    - kubectl set image deployment/myapp myapp=$IMAGE_NAME:$CI_COMMIT_SHORT_SHA
  environment:
    name: production
    url: https://myapp.example.com
  only:
    - tags

說明

  1. Cachego-mod 快取放在專案目錄下,減少 go mod download 時間。
  2. Docker-in-Docker:使用 docker:dind 服務建置映像,並在 docker login 時使用 GitLab CI 內建的 $CI_REGISTRY_USER$CI_REGISTRY_PASSWORD
  3. Deploy:示範如何透過 kubectl 更新 Kubernetes 部署,實務上可改為 Helm、Argo CD 等工具。
  4. Only:測試在所有分支都會跑,建置與部署僅在 maintag 時執行,避免不必要的資源消耗。

常見陷阱與最佳實踐

陷阱 可能的後果 解決方案 / 最佳實踐
未快取相依套件 每次 CI 都要重新下載,耗時 5–10 分鐘。 使用 actions/cache(GitHub)或 cache:(GitLab)快取 go.modgo.sum$GOPATH/pkg/mod
測試不完整 只跑單元測試,忽略整合測試或 e2e,導致上線後錯誤。 在 CI 中加入 go test ./... -tags=integration 或自行撰寫腳本執行容器化測試。
硬編碼路徑或版本 隨著 Go 版本升級,舊的語法或指令失效。 使用變數 go-version: '1.22',並在 go.mod 中聲明最低支援版本。
Docker 映像過大 部署速度慢、資源浪費。 使用 scratchdistroless 基底映像,或在 go build -ldflags="-s -w" 後再 COPY 二進位檔。
機密資訊直接寫在檔案 泄漏金鑰、密碼,造成安全風險。 把所有敏感資料放入 CI 平台的 Secrets,在 workflow 中以 ${{ secrets.NAME }} 取用。
未設定失敗通知 CI 失敗卻不被即時發現,影響交付速度。 加入 Slack、Microsoft Teams、Email 等通知 Action,或在 GitLab 中設定 notifications:

其他實用技巧

  1. 矩陣測試:同時測試多個 Go 版本或不同 OS,確保相容性。
  2. 分階段 (Stage) 控制:測試失敗即停止後續建置,節省資源。
  3. 使用自訂 Action / Docker Image:將共用的建置腳本封裝成 Action,提升團隊一致性。
  4. 產出可追溯的 Artifact:將二進位檔、Dockerfile、測試報告等上傳,方便回溯與審計。
  5. 設定 go.modreplace:在 CI 中測試本地模組變更時,可暫時使用 replace,避免影響正式相依。

實際應用場景

場景 需求 推薦的 CI/CD 設計
開發分支的快速回饋 每次 PR 必須跑完整測試與 lint。 GitHub Actions:on: pull_request,使用 golangci-lint Action,並在失敗時自動在 PR 中留下檢查結果。
發布正式版本 (Release) 產出多平台二進位檔、Docker 映像、發佈說明。 GitHub Actions:on: release 搭配矩陣建置,最後使用 actions/create-release 上傳產物。
持續部署到 Kubernetes 主分支合併即自動滾動更新服務。 GitLab CI:needs: [test]docker-builddeploy,使用 kubectl set image 或 Helm upgrade。
多服務微服務架構 每個微服務獨立測試、建置、部署。 使用 monorepo + path filters(GitHub paths:、GitLab only:changes)只在相關目錄變更時觸發對應 pipeline。
安全合規掃描 必須在每次提交前檢查容器漏洞。 docker-build 階段加入 trivyanchore 掃描,若發現高危漏洞則 exit 1

總結

CI/CD 為 Golang 專案提供 自動化、可靠、可追溯 的開發與部署流程。透過 GitHub ActionsGitLab CI,我們可以在幾分鐘內完成:

  1. 程式碼檢查與快取:減少重複下載與建置時間。
  2. 完整測試與覆蓋率報告:確保每次變更不會破壞既有功能。
  3. 跨平台二進位建置:一次設定,產出 Linux、Windows、macOS 的執行檔。
  4. Docker 映像自動化:從源碼直接產出可部署的容器映像。
  5. 持續部署與回饋:自動推送至 Kubernetes、容器註冊表,並即時通知團隊。

只要遵循 快取、分階段、機密管理、失敗通知 四大原則,便能在實務中快速落地 CI/CD,提升開發速度與產品品質。希望本篇文章的概念說明與範例程式碼,能幫助你在 Golang 專案中建立穩定、可擴充的自動化管道,讓開發團隊更專注於業務邏輯,而不是手動的建置與部署工作。祝你 CI/CD 順利,程式碼永遠保持 綠色