pre-commit&Gitフックでフォーマッターと静的コード解析ツール、テストを実行する

## はじめに
pre-commit&Gitフックでcommit前にフォーマッターと解析ツール、テストを実行させます。
アプリケーションはマイクロサービス(Rails api × Vue)です。開発はDockerを使用します。


## 環境
MacBook Pro intel 2020
macOS ventura 13.5.1
Docker 20.10.21
Docker Desktop　4.14.0 (91374)


**バックエンド**
Rails 7.0.7
ruby 3.2.2


**フロントエンド**
Node.js 18.7.1
Vue 3.3.4
npm 9.8.1


# 実行するツール
ツール自体の具体的な解説は行いません。

#### Rails

| 機能       | ツール   |
|------------|----------|
| テスト     | RSpec   |
| 静的コード解析ツール | rubocop |

#### Vue

| 機能           | ツール   |
|----------------|----------|
| テスト         | Jest    |
| 静的コード解析ツール     | ESlint  |
| フォーマッター | Prettier |

#### スクリプト
pre-commitで自動修正は不要です。修正が必要であるコードを検知するスクリプトを追加しました。

```json
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "check-format": "prettier --check 'src/**/*.{js,vue}'",
    "format": "prettier --write 'src/**/*.{js,vue}'",
    "lint": "eslint --fix 'src/**/*.{js,vue}'",
    "fix": "npm run format && npm run lint",
    "test": "jest"
  },
```

```bash
npm run check-format
```

<br>


## pre-commitとGitフックの設定

.git/hooksにpre-commitがあることを確認します。無い場合は作成します。
```bash
$ cd .git/hooks/
$ ls
commit-msg		pre-commit		prepare-commit-msg
```

実行権限を与えます。
```bash
chmod a+x pre-commit
```

<br>
動作確認してみます。pre-commitにechoを記述します。

```:pre-commit
#!/usr/bin/env bash
echo '呼び出されました'
```

commit前に実行されていることを確認できました。

```
$ git commit -m "pre-commitのテスト"
呼び出されました
[develop#1 8ba2d79] pre-commitのテスト
 1 file changed, 3 insertions(+)
```

## pre-commitの実行順序
1. Prettier
1. ESlint
1. Jest
1. rubocop
1. RSpec

ツールで１つでも警告が出たらcommitを中断します。

<br>

## ツールコマンドの実装
差分が発生した場合、それぞれツールを実行させます。
```
#!/bin/bash

# フロントエンドのチェック
if git diff --cached --name-only --diff-filter=AM | grep '^frontend/'; then
    echo "Running Frontend checks..."

    # Prettier
    echo "Checking formatting with Prettier..."
    docker-compose exec -T frontend npm run check-format
    if [ $? -ne 0 ]; then
      echo "Prettier found formatting inconsistencies!"
      exit 1
    fi

    # eslint
    echo "Linting with ESLint..."
    docker-compose exec -T frontend npm run lint
    if [ $? -ne 0 ]; then
      echo "ESLint found issues!"
      exit 1
    fi

    # frontend tests
    echo "Running Frontend tests..."
    docker-compose exec -T frontend npm run test
    if [ $? -ne 0 ]; then
      echo "Frontend tests failed!"
      exit 1
    fi
fi

# バックエンドのチェック
if git diff --cached --name-only --diff-filter=AM | grep '^backend/'; then
    echo "Running Backend checks..."

    # rubocop
    echo "Linting with RuboCop..."
    docker-compose exec -T backend bundle exec rubocop
    if [ $? -ne 0 ]; then
      echo "RuboCop found issues!"
      exit 1
    fi

    # rspec
    echo "Running RSpec tests..."
    docker-compose exec -T backend bundle exec rspec
    if [ $? -ne 0 ]; then
      echo "RSpec tests failed!"
      exit 1
    fi
fi

echo "All checks passed!"
exit 0


```

```:ディレクトリ構造
tree -L 1
.
├── README.md
├── backend
├── docker-compose.yml
├── frontend
└── web
```

## あとがき
無事実装ができました！これで無駄なGit操作やCI/CDのやり直しが減り、開発に注力できると思います。手動でもcommit前にきちんとツールは実行しましょう！

今回省いたESlintとPrettierの導入について記事を書いています。是非読んでみてください！

https://qiita.com/tech-white/items/145cca4cfaacf3fe60df

<br>

## 参考

https://zenn.dev/yamat47/articles/a9b0b4d937ce03b695e9