Fail-fast = test rẻ chạy trước, test đắt chạy sau; song song hóa tối đa; cache aggressive; chỉ chạy job liên quan tới file thay đổi. Thứ tự stage (rẻ → đắt):
- Lint + format check (5-10s) — fail trước khi develop test khác;
- Type check
tsc --noEmit(10-30s); - Unit tests với watch mode disabled, coverage chỉ trên file thay đổi (30s-2min);
- Build production (1-3min);
- Integration tests (2-5min);
- E2E tests trên staging deploy (5-15min)
Stage sau chỉ chạy nếu stage trước pass. Song song hóa: matrix strategy chạy test split theo file (Jest --shard=1/4), upload coverage artifact → merge ở job cuối. Caching: cache node_modules theo hash của package-lock.json — invalidate khi lock thay đổi; cache Turborepo/Nx outputs để skip rebuild package không đổi (turbo run build --cache-dir=.turbo).
GitHub Actions: actions/cache@v4 với key chuẩn. Affected/changed-only: monorepo dùng nx affected --target=test hoặc turbo run test --filter=...[origin/main] — chỉ test packages bị ảnh hưởng. Concurrency control: GitHub concurrency: group: ci-${{ github.ref }} cancel-in-progress: true — push mới hủy run cũ trên cùng branch. Hidden cost: notification noise (chỉ ping khi main vỡ), flaky test (retry tự động 1 lần, flag để fix sau, không hide bằng --retries=5).