CI 與佈署實務
觀念會了之後,真正能用的 workflow 通常同時做兩件事:確認專案建置成功,以及(在適當的分支)把成品發佈出去。本站的 .github/workflows/ci.yaml 就是一份精簡實例:在 main 被 push 時建置 Zensical 網站,並佈署到 GitHub Pages。
讀一份真實的 workflow
精簡後的結構如下(與本 repo 實際檔案對齊,細節以原始 YAML 為準):
name: ci
on:
push:
branches: [master, main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
steps:
- uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v6
with:
python-version-file: ".python-version"
- run: uv sync --frozen
- run: uv run zensical build --clean
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v4
with:
path: site
- uses: actions/deploy-pages@v4
可以對照前一頁的四層結構:
- 何時跑:push 到
main/master,或手動workflow_dispatch。 - 權限:預設 token 很保守;要寫入 Pages 就必須明確給
pages: write與id-token: write。需要什麼再給什麼,不要開contents: write除非步驟真的要 commit。 - 步驟順序:先 checkout → 安裝工具 → 建置 → 把
site/當 artifact 上傳 → 佈署。前一步失敗,後面不會發佈壞掉的網站。
這就是最小可用的 CI + CD:建置失敗就停,成功才上線。
Secrets 與不要做的事
密碼、API 金鑰、雲端憑證都應放在 repo 的 Settings → Secrets and variables → Actions,在 YAML 用:
GitHub 會自動遮罩 log 裡的 secret 值,但仍不要 echo 出來。
常見事故
- 把
.env、私鑰、token 一起 commit。secret scanning 可能會擋,但不要依賴它當流程。 - 用
pull_request_target搭配 checkout 外部 PR 的程式再執行——惡意 PR 可能偷到 secrets。入門請用pull_request。 - 對第三方 action 只寫
@main而不釘版本。第三方被劫持時,你的 CI 會跟著跑惡意程式。優先用官方 action,版本釘 major 標籤或完整 SHA。
公開 repo 建議開啟 Dependabot alerts 與 secret scanning。官方入門見 Getting started with GitHub security。
只做 CI、不佈署的寫法
多數專案先從「PR 時跑測試」開始,不必一開始就 CD:
name: test
on:
pull_request:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
- run: npm ci
- run: npm test
PR 頁面會出現 checks;沒過就不能(或不該)合併。本機可用 gh pr checks 看同一件事。
建議對照的影片
官方 GitHub Pages 示範兩種來源:從分支發佈,或用 Actions 發佈(與本站做法相同)。
想看完整 CI/CD 觀念與 Docker 範例,見 YouTube 精選 的 TechWorld with Nana。