Git pre-commit Hooks

pre-commit ist ein Framework zum Verwalten und Pflegen mehrsprachiger pre-commit-Hooks.

Eine wesentliche Aufgabe ist es, dem gesamten Entwicklungsteam dieselben Skripte zur Verfügung zu stellen. pre-commit von yelp verwaltet solche pre-commit-Hooks und verteilt sie auf verschiedene Projekte und Entwickler.

Git pre-commit Hooks werden meist verwendet um vor Code Reviews automatisch auf Probleme im Code hinzuweisen, z.B. um die Formattierung zu überprüfen oder Debug-Anweisungen zu finden. Pre-Commit vereinfacht das projektübergreifende Teilen vom Pre-Commit-Hooks. Dabei ist auch die Sprache, in der z.B. ein Linter geschrieben wurde, wegabstrahiert – so ist scss-lint in Ruby geschrieben, Ihr könnt ihn jedoch mit Pre-Commit verwenden ohne Eurem Projekt ein Gemfile hinzufügen zu müssen.

Installation

Bevor Ihr Hooks ausführen könnt, muss der pre-commit-Paketmanager installiert sein.

… auf macOS:

$ brew install pre-commit

… in Eurem Python-Projekt:

$ pipenv install pre-commit

Überprüfen der Installation z.B. mit

$ pipenv run pre-commit -V
pre-commit 2.6.0

Konfiguration

Nachdem Pre-Commit installiert ist, können mit der .pre-commit-config.yaml-Datei im Root-Verzeichnis Eures Projekts Plugins für dieses Projekt konfiguriert werden.

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.5.0
    hooks:
    -   id: check-yaml
    -   id: end-of-file-fixer
    -   id: trailing-whitespace
-   repo: https://github.com/psf/black
    rev: 19.10b0
    hooks:
    -   id: black

Ihr könnt Euch diese Datei auch generieren lassen mit

$ pipenv run pre-commit sample-config
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.4.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: check-added-large-files

Wenn Ihr diesen pre-commit-Hook vor jedem commit ausführen möchtet, installiert diesen mit pre-commit install. Sollen die Hooks manuell ausgeführt werden, kann dies mit pre-commit run --all-files geschehen. Einzelne Hooks können dann auch separat ausgeführt werden, z.B. pre-commit run trailing-whitespace.

Beim ersten Aufruf eines pre-commit-Hooks wird dieser zunächst heruntergeladen und anschließend installiert. Dies kann einige Zeit benötigen, z.B. wenn eine Kopie von node erstellt werden muss.

$ pipenv run pre-commit run --all-files
Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Passed
Check Yaml...............................................................Passed
Check for added large files..............................................Passed
black....................................................................Passed

Eine vollständige Liste der Konfigurationsoptionen erhaltet Ihr in Adding pre-commit plugins to your project.

Ihr könnt auch eigene Hooks schreiben, siehe Creating new hooks.

Ihr könnt die Hooks auch automatisch aktualisieren mit:

$ pipenv run pre-commit autoupdate

Weitere Optionen findet Ihr unter pre-commit autoupdate [options].

Installieren der Git-Hook-Skripte

Damit Pre-Commit auch vor jedem Commit zuverlässig ausgeführt wird, werden die Skripte in unserem Projekt installiert:

$ pre-commit install
pre-commit installed at .git/hooks/pre-commit

Verwenden in CI

Pre-Commit kann auch für Continuous Integration verwendet werden.

Beispiel für GitHub Actions

- name: set PY
  run: echo "::set-env name=PY::$(python -VV | sha256sum | cut -d' ' -f1)"
- uses: actions/cache@v1
  with:
    path: ~/.cache/pre-commit
    key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}

Siehe auch

pre-commit/action

Beispiel für GitLab Actions

my_job:
  variables:
    PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
  cache:
    paths:
      - ${PRE_COMMIT_HOME}

Siehe auch

Weitere Informationen zur Feinabstimmung des Caching findet Ihr in Good caching practices.