iimon TECH BLOG

iimonエンジニアが得られた経験や知識を共有して世の中をイイモンにしていくためのブログです

pre-commitについて

はじめまして。株式会社iimonでバックエンドエンジニアを担当している玉山です。

では早速始めていきます。

前置き

今回はiimonで使っているリンターとフォーマッターをgitの機能でcommitをフックし、レビューのコストを下げてしまおうというお話です。

gitの機能でcommitをフックするには.git/hooks/pre-commitを言うファイルにシェルスクリプトで書けば機能します。

ですが、.git/hooks/pre-commitはgitでの管理対象外の為、履歴が残りません。

そこで今回はpre-commitというフレームワークを使います。

pre-commitのメリットとデメリット

pre-commitは.pre-commit-config.yamlというファイルでgit/hooks/pre-commitを管理しGit管理下におけるというメリットがあります。

デメリットとしてはチーム開発の時にリポジトリをクローン等した時チーム全員がpre-commitを入れ、後述するコマンドを打たないといけないことがあります。

されど、その為だけにCIへわざわざいれなくても個人のローカル環境でリンター、フォーマッターをかけることで開発スピードが上がるので導入を決めました。

iimonではテストはGitHubActionsを使っているのですが、やろうと思えばpre-commitでやることも可能です。

しかし、毎回commit時にテストがかかると時間がかかるのでそこはCIに任せています。

インストール

まずは下記コマンドでインストールしましょう。

$ pip install pre-commit

or

$ brew install pre-commit

参考:https://pre-commit.com/#install

無事インストールできたらバージョンが表示されます。

$ pre-commit --version
pre-commit 3.0.4

試しにつかってみよう

次はサンプルの設定ファイルを作って見ましょう。

プロジェクト直下で下記コマンドを実行して下さい。

$ pre-commit sample-config > .pre-commit-config.yaml

プロジェクト直下に.pre-commit-config.yamlができると思います

中身はこんな感じで基本的なものしか入っていません。

# 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: v3.2.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: check-added-large-files

デフォルトでフック時にチェックしているものはこちらに説明があります。

https://pre-commit.com/hooks.html

適当なファイルの末尾にスペースを追加し、commitしてみましょう。

すると下記のようなエラーが出てcommitできないと思います。

画面はSourceTreeのものになります。

Trim Trailing Whitespace.................................................Failed

この部分がFailedなのでコミットできないことが分かります。

iimonではどうしてる?

最後にiimonで使っている設定を載せておきます。

# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: /migrations/|/static/
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: check-added-large-files
    -   id: detect-aws-credentials
    -   id: detect-private-key

-   repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
    -   id: detect-secrets

-   repo: https://github.com/pycqa/flake8
    rev: 6.0.0
    hooks:
    -   id: flake8
        args: ["--ignore=E203,E501,W503,W504"]

-   repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.0.1
    hooks:
    -   id: mypy
        args: [--ignore-missing-imports]
               # pythonの外部ライブラリを読み込むため
        additional_dependencies: ["types-all"]

-   repo: https://github.com/psf/black
    rev: 23.1.0
    hooks:
    -   id: black
        language_version: python39

-   repo: https://github.com/pycqa/isort
    rev: 5.12.0
    hooks:
    -   id: isort
        args: ["--profile", "black"]

注意

ハマった所としてはYAMLの記法ではあっていても、ハイフンの後に半角スペースを3つ入れないとエラーになった所です。

解説

下記、それぞれ追加したものを解説していきます。

なお追加したものは全て最新のrevにしています。(2022/02/22現在)

余談

どうしてもシェルスクリプトで管理したいんだ!という方は別の方法としてこんな方法もあるみたいです。

https://www.farend.co.jp/blog/2020/04/git-hook/