Client-side hooks (husky + lint-staged): chạy nhanh, kiểm tra cơ bản (format, lint file đã sửa) — UX tốt vì fail trước khi commit.
Server-side CI gate: nguồn chân lý, không thể bypass — luôn phải có vì hook client có thể --no-verify. husky quản lý Git hooks trong package.json/.husky/: pre-commit chạy lint-staged, commit-msg validate conventional commits (commitlint), pre-push chạy test nhanh. lint-staged chạy lệnh chỉ trên file git add đã stage: ví dụ *.ts: eslint --fix, prettier --write — không lint toàn repo (chậm) mà chỉ file thay đổi. Defense in depth:
- Editor: ESLint extension highlight lỗi realtime;
- Pre-commit hook: lint + format file staged;
- Pre-push hook: test fast subset;
- CI: full lint + type check + test + build — bắt mọi thứ hook client bỏ qua. Conventional Commits:
feat: add login,fix(api): handle 401— chuẩn hóa commit message giúp tự generate changelog vớisemantic-release. Lưu ý: hook client quá nặng (chạy full test) → dev frustrated, dùng--no-verify→ mất ý nghĩa
Giữ pre-commit < 5s. CI bypass: cấm push thẳng vào main ở branch protection, require PR + status check pass, require linear history nếu cần.
Client-side hooks (husky + lint-staged): run fast, do basic checks (format, lint changed files) — great UX because they fail before the commit lands.
Server-side CI gates: the source of truth, cannot be bypassed — always required because client hooks can be skipped with --no-verify. husky manages Git hooks via package.json/.husky/: pre-commit runs lint-staged, commit-msg validates conventional commits (commitlint), pre-push runs fast tests. lint-staged runs commands only on staged files: e.g. *.ts: eslint --fix, prettier --write — doesn't lint the whole repo (slow), only changed files. Defense in depth:
- Editor: ESLint extension highlights errors in real time;
- Pre-commit hook: lint + format staged files;
- Pre-push hook: fast test subset;
- CI: full lint + type check + test + build — catches anything client hooks skipped. Conventional Commits:
feat: add login,fix(api): handle 401— standardized commit messages enable automatic changelog generation withsemantic-release. Pitfall: making client hooks too heavy (running the full test suite) → developers get frustrated and use--no-verify→ defeats the purpose
Keep pre-commit under 5s. CI bypass prevention: disallow direct pushes to main via branch protection, require PRs with passing status checks, enforce linear history if needed.