Sổ tay kỹ thuật

pre-commit – chạy ruff, gitleaks trước mỗi commit và trong CI

how-to#git#python#pre-commit#ci· cập nhật 2026-11-06

Dùng khi muốn tự động lint/format Python bằng ruff và chặn commit chứa secret bằng gitleaks, cả trên máy dev lẫn trong GitHub Actions.

Sửa trang này
Mục lục

Tóm tắt: cài pre-commit → viết .pre-commit-config.yaml (pre-commit-hooks, ruff-pre-commit, gitleaks) → pre-commit install để gắn vào .git/hooks/pre-commit → pre-commit run --all-files lần đầu → chạy lại trong CI để chặn người quên cài hook.

Luồng hoạt động

flowchart LR A[git commit] --> B[".git/hooks/pre-commit"] B --> C["pre-commit đọc .pre-commit-config.yaml"] C --> D["hook chạy trên file đã stage"] D -->|pass| E[commit được tạo] D -->|fail hoặc sửa file| F[commit bị chặn] F --> G["git add, commit lại"] E --> H[git push] H --> I["CI: pre-commit run --all-files"]

Cấu hình

Cài đặt

uv tool install pre-commit        # hoặc: pipx install pre-commit
pre-commit --version
cd repo/
pre-commit install                # gắn hook vào repo này (mỗi clone mới phải chạy lại)

File cấu hình

.pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
        args: [--allow-multiple-documents]
      - id: check-added-large-files
        args: [--maxkb=1024]
      - id: check-merge-conflict
      - id: detect-private-key
 
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.17.4
    hooks:
      - id: ruff-check        # linter (id cũ "ruff" vẫn là alias)
        args: [--fix]
      - id: ruff-format       # formatter, đặt sau ruff-check --fix
 
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.30.1
    hooks:
      - id: gitleaks          # build từ source Go; pre-commit tự tải Go nếu máy chưa có

rev phải là tag/commit thật của repo hook. Đừng tự gõ, chạy pre-commit autoupdate để nâng lên tag mới nhất.

Cấu hình ruff trong pyproject.toml

pyproject.toml
[tool.ruff]
line-length = 100
target-version = "py312"
 
[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]   # pycodestyle, pyflakes, isort, bugbear, pyupgrade

Bỏ qua false positive của gitleaks

.gitleaks.toml
[extend]
useDefault = true
 
[[allowlists]]   # gitleaks >= 8.25; bản cũ hơn dùng [allowlist]
description = "file mẫu và test"
paths = ['''tests/fixtures/.*''', '''\.env\.example$''']

Hoặc thêm comment # gitleaks:allow ở cuối dòng bị báo nhầm.

Lệnh

Mục đích Lệnh
Chạy mọi hook trên toàn repo pre-commit run --all-files
Chạy một hook pre-commit run ruff-check --all-files
Chạy trên một số file pre-commit run --files app/main.py app/config.py
Nâng rev lên bản mới nhất pre-commit autoupdate
Bỏ qua tạm một hook SKIP=gitleaks git commit -m "..."
Bỏ qua mọi hook (hạn chế dùng) git commit --no-verify
Gỡ hook khỏi repo pre-commit uninstall
Xoá cache môi trường hook pre-commit clean
Tự cài hook cho mọi repo clone mới có config git config --global init.templateDir ~/.git-template && pre-commit init-templatedir ~/.git-template

Chạy trong GitHub Actions

.github/workflows/pre-commit.yml
name: pre-commit
on:
  pull_request:
  push:
    branches: [main]
 
permissions:
  contents: read
 
jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-python@v7
        with:
          python-version: "3.12"
      - uses: actions/cache@v6
        with:
          path: ~/.cache/pre-commit
          key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
      - run: pipx run pre-commit run --all-files --show-diff-on-failure

Thêm cú pháp workflow xem GitHub Actions cheatsheet.

Lỗi thường gặp

Triệu chứng Nguyên nhân Cách xử lý
Commit bị chặn, hook báo files were modified by this hook Hook (ruff-format, end-of-file-fixer) đã tự sửa file git add -u rồi commit lại
Hook không chạy khi commit Chưa pre-commit install trong clone này pre-commit install
InvalidManifestError hoặc rev không tồn tại Gõ sai tag pre-commit autoupdate
Hook gitleaks cài lâu hoặc lỗi khi build lần đầu Hook gitleaks build bằng Go (pre-commit tự tải Go nếu thiếu, cần Internet) Cài sẵn Go, hoặc đổi id sang gitleaks-system (dùng binary có sẵn) / gitleaks-docker
ruff-check và ruff-format sửa qua lại Rule format conflict (vd E501, ISC001) Đặt ruff-format sau ruff-check, bỏ rule conflict
CI pass nhưng máy dev fail (hoặc ngược lại) Version ruff khác nhau giữa rev và uv.lock Dùng một nguồn version, cập nhật cả hai cùng lúc
gitleaks báo secret đã commit từ trước Secret nằm trong lịch sử Rotate secret, xem git-secret-leak

Tham khảo