Nguyên tắc: test rẻ chạy trước, test đắt chạy sau, song song hoá tối đa, cache mạnh tay, và chỉ chạy job liên quan tới file vừa đổi.
Thứ tự stage (rẻ → đắt), stage sau chỉ chạy khi stage trước xanh:
1. Lint + format check (5-10s)
2. Type check tsc --noEmit (10-30s)
3. Unit test, tắt watch mode, coverage chỉ trên file đã đổi (30s-2 phút)
4. Build production (1-3 phút)
5. Integration test (2-5 phút)
6. E2E test trên bản staging vừa deploy (5-15 phút)
- Song song hoá: matrix strategy chia test theo file (
jest --shard=1/4), upload coverage artifact rồi merge ở job cuối. - Caching: cache
node_modulestheo hashpackage-lock.jsonđể tự invalidate khi lockfile đổi; cache output của Turborepo/Nx để bỏ qua package không đổi (turbo run build --cache-dir=.turbo). Trên GitHub Actions dùngactions/cache@v4. - Chỉ chạy phần bị ảnh hưởng: trong monorepo dùng
nx affected --target=testhoặcturbo run test --filter=...[origin/main]. - Concurrency:
concurrency: { group: ci-${{ github.ref }}, cancel-in-progress: true }để push mới huỷ luôn run cũ trên cùng branch.
Chi phí ẩn ít ai tính: noise thông báo (chỉ nên ping khi main vỡ) và flaky test (retry tự động một lần rồi gắn cờ sửa sau, đừng giấu bằng --retries=5).