「如果你的部署流程需要手冊文件,那它本身就是問題所在。 好的 CI/CD 應該讓你合併 PR 就等於部署完成,其他的都是自動的。」
— DevOps 實踐原則
CI/CD 是什麼?為什麼重要?
CI/CD 是兩個概念的組合:Continuous Integration(持續整合)與 Continuous Delivery/Deployment(持續交付/部署)。 兩者加在一起,目標只有一個:讓程式碼從寫完到上線的距離盡可能短,且過程盡可能安全。
Continuous Integration (CI)
每次有人 Push 或開 PR,自動執行:
- Lint 與型別檢查
- 單元測試與整合測試
- Build 確保編譯不爆炸
Continuous Deployment (CD)
CI 通過後,自動部署到對應環境:
- PR 合併 → staging 環境
- Tag 發布 → production 環境
- 部署失敗自動 rollback
傳統流程 vs CI/CD 流程
❌ 傳統手動流程
✅ CI/CD 自動化流程
為什麼選 GitHub Actions?
CI/CD 工具不只 GitHub Actions 一種。在決定導入之前,了解它和主流替代方案的差異, 幫助你在不同情境做出正確選擇。
| 工具 | 優勢 | 劣勢 | 最適合 |
|---|---|---|---|
| GitHub Actions ⭐ | 與 GitHub 原生整合,YAML 設定,免費額度充足 | 僅限 GitHub 倉庫,複雜邏輯 YAML 難維護 | 個人專案、開源、小型團隊 |
| GitLab CI | 自帶 GitLab SCM,self-hosted 彈性大 | 學習曲線稍陡,需自建 Runner | 企業私有部署、GitLab 用戶 |
| CircleCI | 速度快,平行化能力強,設定簡潔 | 免費額度有限,定價較貴 | 需要高度客製化平行測試的團隊 |
| Jenkins | 高度彈性,插件生態成熟 | 需自建維運,設定複雜,UI 老舊 | 大型企業、複雜 on-premise 流程 |
GitHub Actions 適合你的三個訊號
- • 程式碼已在 GitHub 上:零設定即可使用,PR、Issue、Release 事件直接觸發
- • 需要快速上手:市場上 Action 生態豐富(actions/checkout、setup-node 等),大多數常見任務有現成解法
- • 免費額度夠用:公開 repo 無限制;私有 repo 每月 2,000 分鐘(Linux Runner),個人專案通常足夠
GitHub Actions 核心概念
GitHub Actions 是 GitHub 原生提供的 CI/CD 平台,設定全部寫在 YAML 檔案裡, 放在 .github/workflows/ 目錄下。 理解四個核心概念就能上手 90% 的使用情境。
Workflow
整個自動化流程的定義,對應一個 YAML 檔案。
一個 repo 可以有多個 Workflow,例如 ci.yml、deploy.yml、release.yml。
Event(觸發條件)
什麼動作會觸發 Workflow 執行。
常見:push、pull_request、schedule(定時)、workflow_dispatch(手動觸發)。
Job
Workflow 中的一個執行單位,預設平行執行。
每個 Job 在獨立的 Runner 虛擬機上執行,可設定 needs 讓 Job 依序進行。
Step
Job 中的一個步驟,依序執行。
Step 可以執行 shell 命令(run)或使用既有的 Action(uses),例如 actions/checkout@v4。
層級結構
實戰 ①:基本 CI Workflow
這是一個 Next.js 專案的標準 CI 設定,每次 PR 開啟或更新時,自動執行 Lint、型別檢查和測試。
npm ci vs npm install
npm ci 嚴格按照 package-lock.json 安裝,不會升級版本,確保 CI 環境與本機完全一致。
matrix strategy
可同時在 Node 18、20、22 上測試。每個版本組合是獨立的 Job,平行執行。
actions/cache
cache: npm 會快取 ~/.npm,下次執行直接用快取,從 2 分鐘縮到 30 秒。
實戰 ②:自動部署到 Vercel
CI 通過後,自動部署到 Vercel。這裡用 Vercel CLI 做部署, 比 Vercel 官方 GitHub App 更靈活(可自訂部署邏輯)。
⚙️ 先在 GitHub 設定 Secrets(Settings → Secrets and variables → Actions)
environment: production 的意義
GitHub Environments 讓你可以設定「部署保護規則」:例如要求至少一位 reviewer 核准才能部署, 或是只允許特定分支觸發。設定路徑:Repository → Settings → Environments。 對個人專案這步可省略,但團隊協作強烈建議加上。
實戰 ③:PR Preview 環境
更進階的做法:每個 PR 自動部署一個獨立的 Preview URL,讓 reviewer 可以在真實環境驗證功能, 而不是只看程式碼。
Preview 環境的工作流程
進階技巧
避免並發衝突:concurrency 設定
同一個 PR 快速連推多次,會同時觸發多個 Workflow。用 concurrency 確保同一個 PR 只有最新的 run 在跑,舊的自動取消。
可重用 Workflow:避免重複 YAML
多個 Workflow 共用相同的 CI 步驟?把它抽成 Reusable Workflow,其他地方 uses 引用即可。
環境變數與 Secrets 的層級
| 層級 | 設定位置 | 適用場景 |
|---|---|---|
| Organization Secret | Organization → Settings → Secrets | 多個 repo 共用(例如 NPM_TOKEN) |
| Repository Secret | Repo → Settings → Secrets | 該 repo 專屬(最常用) |
| Environment Secret | Repo → Settings → Environments | Staging / Production 使用不同的值 |
| Workflow env: | YAML 檔案直接寫 | 非敏感設定值(NODE_ENV 等) |
常見錯誤與除錯方式
Permission denied / EACCES 錯誤
原因:Runner 沒有執行特定指令的權限
解法:在 job 層加上 permissions: contents: read(或需要的權限)。GitHub 有預設權限,某些操作需要明確宣告。
Workflow 不觸發
原因:YAML 縮排錯誤,或 on: 條件設錯
解法:用 yamllint 驗證 YAML 格式。注意 branches 是 list,要用陣列格式:branches: [main],不是 branches: main。
Secrets 讀取到空值
原因:Fork 的 PR 預設無法讀取 parent repo 的 Secrets
解法:這是 GitHub 安全設計。解決方案:用 pull_request_target(注意安全風險),或只針對自己 repo 的 branch 部署。
Job 執行時間太長
原因:每次都重新安裝 node_modules
解法:確認 cache: npm 有設定,且 cache-dependency-path 指向正確的 package-lock.json 路徑。
一張圖理解完整 CI/CD 流程
重點整理
CI 的核心價值
讓「壞程式碼」在進入 main 分支前就被攔截,保護主幹的穩定性。
needs: 控制依賴
CI Job 與 Deploy Job 分離,Deploy 等 CI 完成才執行,失敗就不部署。
Secrets 安全存放
所有敏感資訊放 GitHub Secrets,永不寫在 YAML 或程式碼裡。
concurrency 防衝突
同一 PR 多次 push 只跑最新一次,節省 Runner 資源。
Preview 環境
每個 PR 部署獨立預覽 URL,讓 code review 從看程式碼升級為驗證功能。
從小處開始
先設一個簡單的 npm test CI,上線後再逐步加入 CD、Preview、Slack 通知。
上一篇
EP.01 測試金字塔