K čemu je nástroj pre-commit dobrý
Jednou z užitečných funkcionalit Gitu jsou zásuvné moduly (hooks), které mohou při určitých událostech provádět námi definované akce. Například před vytvořením revize (commit) mohou automaticky spouštět nástroje pro kontrolu, opravu a formátování kódu. Je tak mnohem snazší včas odchytávat některé chyby a dodržovat konvence daného projektu, neboli – slovy Pavla Herouta – udržovat „štábní kulturu“. Šetříme tak čas a úsilí jak sobě tak i lidem, kteří provádějí revizi našeho kódu (code review).
Problém ale nastane ve chvíli, kdy chceme svoje zásuvné moduly sdílet mezi projekty s různou strukturou. Nebo chceme volat program vyžadující instalaci jazyka, který v našem projektu nepoužíváme. Proto vznikl nástroj pre-commit, který umožňuje spravovat celou řadu zásuvných modulů Gitu (tedy nejen modul pre-commit
, třebaže se v tomto článku budeme věnovat výhradně jemu) jednoduše a nezávisle na projektu a použitém jazyce.
Vezměme praktický příklad: Před vytvořením revize (commit) chceme automaticky zkontrolovat syntax, zbavit se nadbytečných bílých znaků, předejít úniku soukromých klíčů a opravit konce souborů. Náš projekt je napsaný v jazyce Python a soubory připravené k revizi chceme nejprve opravit a zformátovat pomocí nástrojů isort
a black
, a poté zkontrolovat pomocí flake8
. Toto vše tedy nadefinujeme v souboru .pre-commit-config.yaml
, nainstalujeme balíček pre-commit a (vyjma konfiguračních detailů) se už o nic dalšího zpravidla nemusíme starat.
Instalace
pre-commit lze nainstalovat z pypi.org:
$ python3 -m pip install --user pre-commit
Další možnosti (zipapp, homebrew, conda) jsou popsány v dokumentaci.
Konfigurace
Pro snadné vyzkoušení si naklonujeme repozitář s demonstračními příklady:
$ git clone https://github.com/peberanek/pre-commit-examples
Máme zde soubor example.py
s několika vadami ve zdrojovém kódu, a soubor .pre-commit-config.yaml
, který nám definuje akce popsané v posledním odstavci předchozí kapitoly:
repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: check-yaml # syntax check - id: trailing-whitespace - id: detect-private-key - id: end-of-file-fixer - repo: https://github.com/pycqa/isort rev: 5.12.0 hooks: - id: isort args: ["--profile", "black"] - repo: https://github.com/psf/black rev: 23.3.0 hooks: - id: black - repo: https://github.com/pycqa/flake8 rev: 6.0.0 hooks: - id: flake8 args: ["--max-line-length", "100"]
První akce – neboli plugin nástroje pre-commit – začíná odkazem na repozitář ( repo
) a označením revize nebo tagu ( rev
), které chceme nainstalovat. Následuje výčet zásuvných modulů ( hooks
pro daný plugin), které chceme volat. V našem případě provádět kontrolu syntaxe souborů ve formátu YAML, zbavovat se přebytečných bílých znaků a tak dále.
Jak můžeme vidět u pluginu isort
, použitým nástrojům můžeme předávat i argumenty ( args
) jako při volání z příkazové řádky, což se hodí kdybychom chtěli načítat nějaký externí konfigurační soubor, například:
- repo: https://github.com/PyCQA/bandit rev: 1.7.5 hooks: - id: bandit args: ["-c", "pyproject.toml"] additional_dependencies: ["bandit[toml]"]
Spuštění
Jakmile máme základní konfiguraci hotovou, nainstalujeme pre-commit do našeho gitovského repozitáře:
$ pre-commit install
Nyní se nám při každém vytváření revize ( git commit
) zavolají vybrané pluginy automaticky. Pokud si chceme funkčnost ověřit bez nutnosti vytvářet novou revizi, jde to udělat následovně:
$ pre-commit run --all-files
--all-files
pracuje pre-commit pouze se soubory připravenými k revizi (stage).Jak můžeme vidět na obrázku, pre-commit odhalil několik problémů.isort
ablack
automaticky opravily řazení importů a formátování. Zapomenutý soukromý klíč (který se v reálu v repozitáři vůbec nesmí objevit) a nepoužitý modulsys
odstraníme manuálně. Jakmile jsou problémy opravené, při tvorbě další revize (git commit -a
) již všechny kontroly projdou.
Jednotlivé pluginy a jejich zásuvné moduly lze volat i samostatně, například pouzeblack
(voláme pomocí hodnoty klíčeid
z konfigurace výše):
$ pre-commit run black
Shrnutí a další odkazy
V článku jsme si ukázali jednoduché nastavení a použití správce gitovských zásuvných modulů nazvaného pre-commit. Ten nám může usnadnit automatizaci některých rutinních akcí a ve svém důsledku tak i pomoct k více konzistentnímu a kvalitnějšímu kódu.
V případě, že vás nástroj zaujal, mohl by vás zajímat přehled použití a správa z příkazové řádky, využití v rámci Průběžné integrace (CI) nebo tvorba vlastních zásuvných modulů pro pluginy.
(Autorem obrázků je Petr Beránek.)