Ba mức, chọn theo độ phức tạp của repo:
1. Path filter — khai báo mỗi workflow chỉ kích hoạt khi đường dẫn tương ứng thay đổi.
on:
pull_request:
paths: ['services/payments/**', 'packages/shared/**']Đơn giản, nhưng bỏ sót phụ thuộc gián tiếp: sửa một package dùng chung, service phụ thuộc nó không chạy test nếu quên khai báo đường dẫn đó.
2. Đồ thị phụ thuộc — dùng build tool hiểu quan hệ giữa các package (Nx affected, Turborepo filter, Bazel) để tính tập bị ảnh hưởng từ diff, gồm cả phụ thuộc bắc cầu. Chính xác hơn nhiều và không phải bảo trì danh sách path bằng tay.
3. Cache theo nội dung — task được hash từ input (source + config + dependency); trùng hash thì lấy kết quả cache thay vì chạy lại. Kết hợp remote cache thì việc đã chạy ở PR khác không phải chạy lại.
Ba điểm cần cảnh giác:
- So sánh với base sai gốc. Diff phải tính từ merge-base với nhánh đích, không phải commit cuối; sai gốc dẫn tới bỏ sót hoặc chạy dư toàn bộ.
- Thay đổi ở gốc repo (lockfile, Dockerfile chung, cấu hình CI) thực chất ảnh hưởng mọi thứ — cần quy tắc chạy toàn bộ trong trường hợp này.
- Required status check với job bị skip: nếu check bắt buộc không chạy, PR có thể kẹt vĩnh viễn. Cần job tổng hợp luôn chạy và báo trạng thái cuối.