沒有 CI/CD 的雲原生 = 用跑車載貨,但每次都要手推上去

Analysis → Design → Development → Testing → Deployment → Maintenance。$ npm test
✓ all tests passed
$ echo $?
0 # ← 0 = 成功$ npm test
✗ 1 test failed
$ echo $?
1 # ← 非 0 = 失敗學會這個抽象模型,換工具只是換語法

push)、合併請求 (pull_request) 或定時排程 (schedule),是觸發自動化流程的起點。run) 或使用一個別人寫好的 Action (uses)。Stage 的概念來組織 Job。
GitLab CI 多了 Stage 這層,用來分組 Job 並控制執行順序。你可以想像 Stage 是「橫向群組」,Job 則是「群組裡的成員」。
Stage 來組織 Job,但也有其獨特的詞彙。
Stage 的概念。主要差異在於執行機器稱為 Agent (而非 Runner),以及單一步驟分為 Step / Task 兩層。needs: 處理任務依賴關係。學會 GitHub Actions,讀懂 GitLab CI / Azure Pipelines 的設定也大致能理解其核心邏輯。
jobs:
test: # job 名字
runs-on: ubuntu-latest # 跑在哪台機器
steps: # 步驟列表
- run: npm test # - 開頭表示 list 的一個元素
- run: npm run lint- 開頭,縮排決定誰是誰的子層name: Hello GitHub Actions # workflow 名字
on: # 什麼時候要跑
push:
branches:
- "**"
jobs: # 要做哪些事
hello-job:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4 # uses = 用現成 action
- name: Say Hello
run: echo "Hello World!" # run = 跑一行 shell.github/workflows,push 到任意分支就會跑。name: Node CI
on:
push:
branches:
- "**"
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm install
- run: npm testactions/upload-artifact@v4Container Image = 雲原生的 Deployment Artifact
不可變、可複製、隨處可跑
- name: Deploy
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
API_KEY: ${{ secrets.PROD_API_KEY }}
run: ./deploy.shdocker compose up 換成 kubectl apply 而已。cicd-lab/
├── .github/
│ └── workflows/ # ← 一開始是空的
├── snippets/
│ ├── 01_hello.yaml # Lab-01 會用
│ ├── 02_run-test.yaml # Lab-02 會用
│ ├── ci.yaml # Lab-04 會用
│ └── cd.yaml # Lab-04 會用
├── src/
│ ├── app.ts # Fastify app (可測試)
│ └── server.ts # 啟動 server
├── test/
│ └── app.test.ts # Vitest 測試
├── Dockerfile
├── docker-compose.yml
└── package.jsonsnippets/ 資料夾裡。我們會分階段引導你將它們複製到 .github/workflows/,這樣就能一步步感受 CI/CD Pipeline 的演進。<> Code 按鈕 → 選擇 Codespaces → 點擊 Create codespace on main。node --version
docker --version
docker compose version
act --version# 安裝依賴
npm ci
# 啟動服務
npm run build
npm run startcurl http://localhost:3000/
curl http://localhost:3000/health{"status":"ok"} 之類的回應npm testsrc/app.ts 檔案,將 /health 端點的回應內容改錯。再次執行 npm test,這時您應該會看到測試失敗(紅色)。src/app.ts 恢復原狀,否則後續推送 (push) 時,CI 將會持續失敗。snippets/01_hello.yaml 的檔案複製到 .github/workflows/ 目錄下,並推送到新的分支:git checkout -b feature/ci-observe
cp snippets/01_hello.yaml .github/workflows/
git add .
git commit -m "ci: add hello.yaml"
git push origin feature/ci-observe
echo "Hello World!" 命令,輸出至 log。ls -al 命令,列出 checkout 後的檔案結構,驗證程式碼已存在。Checkout code 步驟後,您的程式碼才會被複製到這個環境中,供後續步驟使用。snippets/02_run-test.yaml 的檔案複製到 .github/workflows/ 目錄下,並推送到您目前的分支:cp snippets/02_run-test.yaml .github/workflows/
git add .
git commit -m "ci: add run-test.yaml"
git push origin feature/ci-observe

act 是一個強大的工具,能讓您在本地端執行 GitHub Actions workflow,對於除錯和快速迭代 CI/CD 流程非常有幫助。act 工具不僅能模擬完整的 CI/CD 流程,還能模擬特定的事件類型(例如 push),讓您在本地端就能測試 Workflow,大幅提升開發效率。act push 模擬推送事件:act push-W 參數:act push -W .github/workflows/01_hello.yaml
act push -W .github/workflows/02_run-test.yaml--env GITHUB_REF 參數:act push --env GITHUB_REF=refs/heads/your-feature-branchact 會自動拉取必要的 Docker 映像檔 (例如 catthehacker/ubuntu),這可能需要約 1-2 分鐘。為了節省時間,您可以在課程開始前先執行 docker pull catthehacker/ubuntu:act-latest 預先拉取映像檔。hello.yml 和 run-test.yaml 已經讓您對 GitHub Actions 有了基本認識。但業界真實的 CI/CD pipeline 會比這兩個檔案執行更多複雜的任務。snippets/ci.yml 和 snippets/cd.yml 這兩個進階設定檔,了解它們如何處理更複雜的 CI/CD 流程。act 進行模擬。snippets/ci.yaml 與 snippets/cd.yaml,看看它們是如何實現這些進階目標的。snippets/ci.yml,從頭開始解析這個進階的 CI Workflow 設定。name: ci
on:
push:
branches: [ '**' ] # 所有 branch 都跑
pull_request: # PR 也跑
permissions:
contents: read # 最小權限原則
on)push 到任何分支時自動觸發。同時,當有新的 pull_request 被建立或更新時,也會觸發 CI 流程,確保每次合併前程式碼都能通過測試。permissions)contents: read) 的權限。這是一個重要的安全實踐,避免因權限過大而造成潛在的資安風險。concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: truestrategy:
fail-fast: false
matrix:
node-version: ['22', '24']- name: Checkout
uses: actions/checkout@v4 # 抓 code
- name: Setup Node.js
uses: actions/setup-node@v4 # 裝 Node
with:
node-version: ${{ matrix.node-version }}
cache: npm
- name: Install dependencies
run: npm ci # 裝依賴
# add your steps here, e.g. lint, test, build etc.
# - run: npm run typecheck # 型別檢查
# - run: npm run ci # lint + test- name: Compute image tag
id: meta
run: |
BRANCH_NAME="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
if [[ "$BRANCH_NAME" == release/* ]]; then
VERSION="${BRANCH_NAME#release/}"
IMAGE_TAG="release-${VERSION}"
else
IMAGE_TAG="sha-${GITHUB_SHA::7}"
fisha-a1b2c3drelease-1.4.0- name: Build Docker image
if: ${{ matrix.node-version == '24' }}
run: docker build -t my-app:${{ steps.meta.outputs.image_tag }} .
# 另一個 job
cd:
if: ${{ startsWith(github.ref, 'refs/heads/release/') }}
needs: ci
uses: ./.github/workflows/cd.ymlon:
workflow_dispatch: # 可手動觸發
workflow_call: # 可被 ci.yml 呼叫
jobs:
deploy:
if: ${{ startsWith(github.ref_name, 'release/') }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Compute release image tag
...
- name: Build and deploy with Docker Compose
run: docker compose up -d --build
- name: Verify health endpoint
run: curl -fsS http://localhost:3000/healthci.yaml 和 cd.yaml 複製到您的 workflows 目錄:cp snippets/ci.yaml .github/workflows/
cp snippets/cd.yaml .github/workflows/git checkout -b feature/a
act push
docker images # 查看 build 出來的 imagesha-a1b2c3d 的格式,這代表了本次commit的 SHA 值。git checkout -b release/1.0.0
act push
docker images # 查看 release tag imagerelease-1.0.0,同時也會觸發後續的 CD 流程。act push 會模擬完整的 GitHub Actions 執行環境。在 Codespaces 中首次執行時,可能需要下載 Docker 映像檔,請耐心等待。docker compose up -d --build —CD 重 build 一次 image。但前面說 image 是 immutable artifact、build once run anywhere。.github/workflows/ci.yml 的 steps 加:- name: Format check
run: npm run format:check
- name: Lint
run: npm run lintact push 會看到這兩步驟有跑src/app.ts,加一個 /version endpoint:app.get('/version', async () => {
return { version: process.env.APP_VERSION || 'dev' };
});test/app.test.ts 加對應的測試。npm test 全綠act push 能完整跑過 CInpm install # 第一次
npm start # 跑起來
npm run dev # 熱重載npm run typecheck # 型別檢查
npm test # 跑測試
npm run lint # lint
npm run format:check# 模擬 push 事件(預設跑全部)
act push
# 只跑 ci.yml
act push -W .github/workflows/ci.yml
act pull_request # 模擬 PR 事件
act -j test # 只跑名為 test 的 job
act -l # 列出所有 workflow 跟 jobnpm test)寫 code → CI 自動驗 → 推 release branch → CD 自動部署
CI/CD「主動推」變更到部署環境(Push 模型)
核心精神:Git 就是 K8s cluster 的唯一真相