Alat kualitas dari dua Chapter sebelumnya hanya berguna bila dijalankan — dan kenyataannya orang (termasuk kita) kadang lupa menjalankan ruff sebelum git commit, lalu CI di server yang memerah. Git punya mekanisme bawaan untuk menutup celah lupa ini: hooks, skrip yang dieksekusi otomatis pada momen tertentu, salah satunya tepat sebelum commit dibuat. Pada Chapter ini kita memasang pemeriksaan kualitas ke hook pre-commit dengan bantuan tool bernama pre-commit (tanda hubung memang bagian dari namanya).

Konsep Git Hook #

Folder tersembunyi .git/hooks/ di setiap repository berisi skrip yang git jalankan pada momen tertentu. File bernama pre-commit, bila ada dan dapat dieksekusi, berjalan sebelum commit benar-benar tercipta; exit code bukan nol membatalkan commit tersebut. Menulis skrip hook manual berarti setiap anggota tim harus memasangnya sendiri di masing-masing mesin — dan hook tidak ikut ter-commit ke repository. Tool pre-commit menyelesaikan keduanya sekaligus: konfigurasi hook disimpan sebagai file proyek, lalu tool memasang skrip penghubung ke .git/hooks/pre-commit dengan satu perintah.

Anatomi .pre-commit-config.yaml #

Konfigurasi disimpan di akar repository dengan nama .pre-commit-config.yaml:

yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: end-of-file-fixer
      - id: trailing-whitespace

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.17.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

Mari kita bedah strukturnya:

  1. repos: daftar repository sumber hook. Setiap hook hidup di repo yang dikelola terpisah, sehingga bisa diperbarui tanpa menunggu rilis tool utamanya.
  2. repo: https://github.com/pre-commit/pre-commit-hooks: kumpulan hook serbaguna dari maintainer pre-commit sendiri.
  3. rev: v5.0.0: versi hook yang dikunci — semua anggota tim memakai versi sama, hasil pemeriksaan pun konsisten.
  4. id: end-of-file-fixer: memastikan setiap file diakhiri satu baris kosong baku; trailing-whitespace menghapus spasi menempel di akhir baris.
  5. repo: .../ruff-pre-commit dengan id: ruff: menjalankan linter ruff versi 0.17.0; args: [--fix] memperbaiki temuan aman secara otomatis.
  6. id: ruff-format: menjalankan formatter pada file yang di-commit.

File YAML di atas sudah diperiksa keabsahan strukturnya (parsing valid), dan nomor versi rev mengikuti pola rilis resmi tiap repo hook.

Memasang dan Menjalankan #

Instalasi tool dilakukan sekali per mesin:

bash
python3 -m pip install pre-commit
pre-commit install

Output yang Dihasilkan (ilustrasi — teks persisnya menyesuaikan versi tool dan sistem operasi):

text
pre-commit installed at .git/hooks/pre-commit

Mulai saat itu, setiap git commit menjalankan seluruh hook pada file yang staging. Ringkasan hasilnya terlihat seperti berikut:

Output yang Dihasilkan (ilustrasi):

text
end-of-file-fixer.........................................................Passed
trailing-whitespace......................................................Passed
ruff...........................................................................Passed
ruff-format..............................................................Passed

Hook yang memodifikasi file (misalnya ruff --fix yang menghapus import tak terpakai) menandai dirinya Failed sambil memperbaiki file tersebut; git membatalkan commit pertama dan kita diminta git add ulang lalu commit sekali lagi dengan file yang sudah bersih.

Untuk mencoba seluruh hook tanpa melakukan commit:

bash
pre-commit run --all-files

Perintah ini berguna saat pertama kali memperkenalkan pre-commit ke proyek lama — lebih baik memperbaiki seluruh temuan di satu sesi daripada terkejut hook gagal di tengah commit mendesak.

Hook Populer untuk Proyek Python #

HookTugasnya
rufflinting dan perbaikan otomatis gaya kode Python
ruff-formatformatting konsisten seluruh tim
end-of-file-fixerbaris kosong penutup file
trailing-whitespacespasi menempel di ujung baris
check-yamlmemastikan file YAML bisa di-parse sebelum masuk repo

Hook menjaga titik masuk perubahan di mesin lokal. Lapisan terakhir berada di server: memastikan seluruh test dan linter benar-benar hijau sebelum perubahan menyatu ke branch utama — tugas continuous integration pada Chapter berikutnya.