CI/CD 工具安裝與環境設定

從零開始建立 CI/CD 執行環境:涵蓋 GitHub Actions、GitLab CI、Jenkins 安裝,以及 Runner、Secrets 與本地測試工具的完整設定流程。

GitHub Actions 入門設定

GitHub Actions 是 GitHub 原生的 CI/CD 服務,無需安裝任何伺服器。只需在專案根目錄建立 .github/workflows/ 資料夾,並新增 YAML 工作流程檔案即可啟用。每個 .yml 檔案代表一條獨立的 workflow,可依功能拆分,例如 ci.yml(測試)與 release.yml(發佈)分開管理,讓整體設定結構更清晰易讀。GitHub 會在每次符合觸發條件的事件發生時,自動掃描 .github/workflows/ 資料夾並執行對應的工作流程。

# .github/workflows/ci.yml — 完整的 GitHub Actions 工作流程範例
name: CI Pipeline

on:
  push:
    branches: [main, develop]     # push 到 main 或 develop 時觸發
  pull_request:
    branches: [main]              # 向 main 發起 PR 時觸發
  schedule:
    - cron: '0 2 * * 1'           # 每週一凌晨 2 點自動執行(排程觸發)

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: true             # 矩陣中任一失敗立即取消其餘
      matrix:
        node-version: [18, 20, 22]  # 矩陣測試多個 Node.js 版本
    steps:
      - name: 取出程式碼
        uses: actions/checkout@v4

      - name: 設定 Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'            # 自動快取 npm 相依套件

      - name: 安裝相依套件
        run: npm ci               # ci 指令確保安裝結果與 lock 檔完全一致

      - name: 執行 Lint 檢查
        run: npm run lint

      - name: 執行單元測試
        run: npm test -- --coverage

      - name: 建置專案
        run: npm run build

      - name: 上傳建置產物
        uses: actions/upload-artifact@v4
        with:
          name: dist-node${{ matrix.node-version }}
          path: dist/
          retention-days: 7       # 7 天後自動清除,節省儲存空間
GitHub Actions 免費方案每月提供 2,000 分鐘(公開倉庫無限制)。矩陣策略可同時測試多個版本或平台,但會乘算執行分鐘數,建議僅在關鍵分支(如 main)啟用完整矩陣,功能分支可縮減為單一版本以節省配額。

工作流程目錄結構建議如下,依職責分檔管理,避免單一 YAML 過於龐大。明確的命名方式能讓整個團隊一眼看出每條 workflow 的觸發時機與用途:

.github/
└── workflows/
    ├── ci.yml          # 測試與 Lint(所有分支 push 時觸發)
    ├── release.yml     # 建置與發佈(語意化版本 tag 觸發)
    ├── deploy.yml      # 部署至伺服器(main 分支 push 觸發)
    └── scheduled.yml   # 定期任務(cron 排程,例如安全掃描)
Workflow 檔案名稱不影響功能,但建議使用小寫加連字號的命名方式,例如 build-and-test.yml,與 GitHub UI 顯示的 workflow 名稱保持一致。每個 workflow 檔案都能在 GitHub 網站的「Actions」分頁中獨立查看執行歷史與 log。

GitLab CI 設定(.gitlab-ci.yml)

GitLab CI 設定集中於專案根目錄的 .gitlab-ci.yml。所有 stages 和 jobs 都定義在這一個檔案中,GitLab 在每次 push 時自動偵測並觸發 Pipeline。隨著專案規模增長,可使用 include 關鍵字將設定拆分至多個子檔案,例如將 Docker 相關 job 抽離為 .gitlab/ci/docker.yml,提升可維護性並讓團隊成員各自負責自己熟悉的部分。

# .gitlab-ci.yml — 包含四個 stage 的完整設定範例
stages:
  - lint       # 程式碼品質檢查(最快,優先執行,秒級完成)
  - test       # 單元測試與整合測試(含覆蓋率報告)
  - build      # 建置 Docker 映像或靜態資源
  - deploy     # 部署至目標環境(可設定手動核准)

variables:
  NODE_ENV: production
  DOCKER_DRIVER: overlay2
  FF_USE_FASTZIP: "true"        # GitLab Runner 效能旗標,加速 artifact 壓縮

default:
  image: node:20-alpine         # 所有 job 預設使用此 Docker 映像
  before_script:
    - npm ci --cache .npm --prefer-offline
  cache:
    key:
      files:
        - package-lock.json     # 依 lock 檔案雜湊值建立 cache key
    paths:
      - .npm/                   # 快取 npm 下載目錄,而非 node_modules

lint:
  stage: lint
  script:
    - npm run lint
    - npm run typecheck
  allow_failure: false          # lint 失敗則阻止後續所有 stage 執行

test:
  stage: test
  script:
    - npm run test -- --coverage --ci
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'   # 解析覆蓋率數字顯示於 MR
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
    expire_in: 3 days

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/                   # 傳遞給 deploy stage 使用
    expire_in: 1 hour

deploy-staging:
  stage: deploy
  script:
    - echo "部署到測試環境..."
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"   # 只在 main 分支自動部署
lint stage 應放在最前面,因為 Lint 執行速度最快(通常在 30 秒內完成),能在耗時的測試與建置之前就攔截明顯的程式碼問題,節省整體 Pipeline 時間,同時讓開發者更快收到反饋。

Runner 設定:GitHub-hosted vs Self-hosted

Runner 是實際執行 CI/CD 任務的工作節點,負責接收平台派發的 job 並在獨立環境中執行腳本。選擇哪種 Runner 類型取決於安全性需求、網路環境與成本考量:

# GitHub-hosted Runner — 零設定,直接指定系統映像
jobs:
  build:
    runs-on: ubuntu-latest      # 也可用 windows-latest / macos-latest
    # GitHub 自動分配虛擬機(2 核 7GB RAM),任務完成後立即回收

# Self-hosted Runner — 需自行安裝,但可存取內網資源與自訂環境
jobs:
  deploy:
    runs-on: [self-hosted, linux, deploy]   # 以 labels 篩選指定 Runner

安裝 Self-hosted Runner(GitHub Actions):前往 GitHub Repo → Settings → Actions → Runners → New self-hosted runner,依畫面提供的指令完成安裝。

# 以下為 Linux x64 安裝範例(版本號請以 GitHub 頁面顯示為準)
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.317.0.tar.gz -L \
  https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz
tar xzf actions-runner-linux-x64-2.317.0.tar.gz

# 設定 Runner(貼上 GitHub 頁面提供的一次性 token)
./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO \
            --token YOUR_REGISTRATION_TOKEN \
            --labels "deploy,production"   # 自訂標籤,供 runs-on 篩選

# 以系統服務方式啟動(建議用於正式環境,確保重開機後自動重啟)
sudo ./svc.sh install
sudo ./svc.sh start

安裝 GitLab Runner(Self-hosted):以 Docker 方式部署是生產環境的推薦做法,隔離性佳且升級方便。

# 以 Docker 方式運行 GitLab Runner(推薦用於生產)
docker run -d \
  --name gitlab-runner \
  --restart always \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gitlab/gitlab-runner:latest

# 前往 GitLab → Settings → CI/CD → Runners 取得 Registration Token
# 再執行 register 指令完成與 GitLab 的配對
sudo gitlab-runner register \
  --non-interactive \
  --url "https://gitlab.com/" \
  --registration-token "YOUR_TOKEN" \
  --executor "docker" \
  --docker-image "docker:24.0" \
  --description "production-runner" \
  --tag-list "deploy,build,docker" \
  --docker-privileged
為 Runner 設定 tags(labels)後,可在 job 中使用 tags:(GitLab)或 runs-on:(GitHub)指定由特定 Runner 執行,確保部署任務只在具有正式環境存取權限的機器上執行,避免在共用 Runner 上暴露敏感憑證。

環境變數與 Secrets 安全管理

CI/CD 管線中常需要存取 API 金鑰、資料庫密碼、SSH 私鑰等敏感資訊。這些資訊絕對不能直接寫在程式碼、YAML 設定檔或 Dockerfile 中,應使用平台提供的 Secrets 機制,讓 CI 平台在執行時以環境變數方式動態注入,確保敏感資料不會出現在任何版本控制紀錄中。

永遠不要將 Secrets 硬編碼在 YAML 或 Dockerfile 中。即使之後提交刪除的 commit,Git 歷史紀錄仍會永久保留明文,攻擊者只需執行 git log -p 即可取得。一旦洩漏,應立即在服務商後台撤銷並重新生成新的金鑰。
# GitHub Actions — 在 Repository Settings → Secrets and variables → Actions 新增
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production    # 使用 Environment Secrets(可設定審核保護機制)
    steps:
      - name: 部署至正式伺服器
        env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}      # 敏感:SSH 私鑰
          SERVER_HOST: ${{ secrets.PROD_SERVER_HOST }}   # 敏感:伺服器 IP/域名
          APP_ENV: ${{ vars.APP_ENV }}                   # 非敏感:一般設定值用 vars
        run: |
          echo "$DEPLOY_KEY" > /tmp/deploy_key
          chmod 600 /tmp/deploy_key
          ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no \
              user@$SERVER_HOST "./deploy.sh"
          rm -f /tmp/deploy_key               # 使用後立即刪除金鑰檔,避免洩漏

# GitLab CI — 在 Settings → CI/CD → Variables 新增(可設定 Protected / Masked)
deploy:
  stage: deploy
  script:
    - echo "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USER" --password-stdin
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest
GitHub Actions 的 Secrets 可設定於 Repository、Environment 或 Organization 三個層級。Environment Secrets 可搭配「Required reviewers」審核保護,確保正式環境部署需要人工批准後才能執行。GitLab 的 Variables 則可設定「Protected」(僅限受保護分支存取)與「Masked」(在 Pipeline log 中隱藏輸出)兩種保護模式,建議正式環境金鑰兩者都勾選。

本地測試 CI 設定(act 工具)

每次修改 CI 設定就需要推送程式碼才能驗證,既耗時又浪費 Pipeline 執行分鐘數,尤其在除錯 YAML 語法或 step 邏輯時格外痛苦。act 工具可在本機使用 Docker 容器模擬 GitHub Actions 執行環境,讓你在推送前即時驗證工作流程是否正確,大幅縮短 CI 開發的回饋循環。

# 安裝 act
brew install act              # macOS(Homebrew)
choco install act-cli         # Windows(Chocolatey)
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash  # Linux

# 首次執行時 act 會詢問 Runner 映像大小(建議選 Medium,約 500MB)
act

# 常用指令
act --list                                    # 列出所有可用的 workflow 與 job
act push                                      # 模擬 push 事件,執行所有對應 workflow
act push --job build-and-test                 # 只執行指定名稱的 job
act pull_request                              # 模擬 PR 事件(測試 PR 觸發的 job)
act workflow_dispatch                         # 模擬手動觸發事件

# 指定較小的 Docker 映像(加快首次下載速度,適合 CI 環境)
act push -P ubuntu-latest=catthehacker/ubuntu:act-20.04

# 傳入本地 Secrets 檔案進行測試(格式與 .env 相同)
act push --secret-file .env.secrets

# Dry Run 模式(只驗證 YAML 語法與 job 結構,不實際執行)
act push --dryrun
在專案根目錄建立 .actrc 檔案可保存常用的 act 設定,例如:
-P ubuntu-latest=catthehacker/ubuntu:act-20.04
--secret-file .env.secrets
這樣每次執行 act 時就會自動套用,不需要重複輸入參數。記得將 .env.secrets 加入 .gitignore,避免本地測試用的金鑰被意外提交。

常見設定錯誤與排除方法

以下是初學者最常遇到的 CI/CD 設定問題,以及對應的診斷方式與解決步驟。遇到問題時,優先查看 Pipeline log 的完整輸出,錯誤訊息通常已清楚指出問題所在:

環境設定完成後,前往 Pipeline 設計 學習如何設計高效的多 stage 工作流程、條件執行策略,以及 artifact 與 cache 的差異與最佳實踐。