CI/CD 骨架
搭建 GitHub Actions 流水线,在每个 PR 上门控 build + test + lint。
为什么
在每个 PR 上跑的 CI 骨架是你能装的最便宜的防 bug 手段。它让'在我机器上能跑'变得无关,因为机器现在是干净的 runner。没有它,坏代码静默合入,第一个发现坏的是部署到 prod 的人。骨架还创建部署跑道:一旦 CI 里 build+test 绿了,加部署步骤是 10 行 job,不是一个项目。没有这个骨架的团队最终用 rsync 从笔记本部署,这就是 prod 在周五挂掉的原 因。
何时使用
紧跟 project-init,在第一个功能 PR 之前。约 30-45 分钟。仅当仓库永远不会有 >1 贡献者时可跳过。
如何做
1. 创建 .github/workflows/ci.yml,在 PR + push main 时触发 - jobs: lint、test、build——并行跑,全过才放行 2. 用 setup-node action 带 cache: 'pnpm' 跳过重装 - actions/setup-node@v4,node-version-file: '.nvmrc' - run: pnpm install --frozen-lockfile 3. lint 快速失败,test 慢速 - lint: 30s 超时,任何警告即失败 - test: 10min 超时,跑 vitest --coverage - build: 产出 artifact,上传供 deploy job 用 4. 加 deploy job,门控 branch == main && CI 通过 - uses: needs: [lint, test, build] - if: github.ref == 'refs/heads/main' - 部署到 staging;prod 需手动审批(environment: prod) 5. 在仓库设置里保护 main 分支 - 要求状态检查:ci/lint、ci/test、ci/build - 要求 1 个评审 + 合并前分支最新
示例
# .github/workflows/ci.yml
name: ci
on: { pull_request: {}, push: { branches: [main] } }
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version-file: '.nvmrc', cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- run: pnpm lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version-file: '.nvmrc', cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- run: pnpm test --coverage常见问题
- ⚠CI 里不用 --frozen-lockfile,队友的脏 lockfile 静默改变所有人的版本。
- ⚠缓存 node_modules 而非 pnpm store——缓存键永远不正确失效,得到过时依赖。
- ⚠把所有 job 跑在一个巨型 job 里而非并行——PR 反馈要 12 分钟而非 3 分钟。
- ⚠忘了分支保护,有人能直接推 main 绕过 CI。
最佳实践
- ✓每个 action 锁主版本(@v4)并用 Dependabot 升级——未锁的 action 在上游发坏版本时静默坏掉。
- ✓每个 job 设 timeout-minutes,让挂起进程失败 PR 而非跑 6 小时。
- ✓用 concurrency 组取消同分支上被取 代的运行——省 50%+ CI 分钟。
- ✓密钥放 GitHub Environments(非仓库级),staging 密钥不会泄漏到 PR fork。