shwldshwld17 days ago

lefthookでbun installの実行チェックをpre-commitに入れる

bun.lock が更新されたのに bun install を実行していないままコミットしようとすると、CIや他の開発者の環境で依存関係がズレる。lefthook の pre-commit に依存関係チェックを入れることで、このミスをコミット前に防ぐ。

Before: bun install を忘れてコミットしても気づけない。 After: node_modules/.bin のタイムスタンプと bun.lock を比較し、古ければコミットをブロックする。

# lefthook.yml
assert_lefthook_installed: true

pre-commit:
  commands:
    deps-check:
      run: |
        if [ ! -d node_modules/.bin ] || [ bun.lock -nt node_modules/.bin ]; then
          echo "node_modules が古いです。bun install を実行してください。"
          exit 1
        fi

設計のポイント:

  1. assert_lefthook_installed: true — lefthook バイナリが見つからない場合に hook 実行自体を exit 1 で失敗させる公式オプション。新規参加者がインストールを忘れても気づけるようになる
  2. node_modules/.bin をタイムスタンプ比較の対象にするbun install はパッケージに変更がない場合でも .bin のタイムスタンプを更新する(公式ドキュメントに明記はないが実装の観察値)。一方 node_modules ディレクトリ直下は変更がなければタイムスタンプが変わらないことがあり、「install 済みなのに古いと判定される」フォールスポジティブが起きた。.bin を対象にすることでこの問題を回避できる
  3. -nt(newer than)演算子 — bash の [[ A -nt B ]] で A が B より新しいか判定できる。bun.lock -nt node_modules/.bin は「lockfileの方が新しい=install未実行」を意味する

lefthook の setup フックは staged ファイルがない状態では skip されることがあるため、commands の先頭に deps-check を入れる方が確実にブロックできた。