docker環境でcommit時にlinterを実行

## 環境
- intel Mac
- VSCode

## 前回記事
- 以下の記事にprettierやeslintの設定を書いてあります。
- まだ読んでいない方はぜひこちらからどうぞ
    - [prettierやlinterの設定](https://qiita.com/kawataku-89love/items/a2912ee7e8fbe7b93f46)

## huskyとは

- git hookと言ってある特定のgitの操作をしたら指定してあったコマンドを実行する
- そのgit hookを手助けしてくれるものがhusky君

## lint-stagedの実行

- staging環境(git addされたもの)にあるファイルに対して、commitのタイミングでコマンドを実行できる
    - lint-stagedに登録したものがcommitのタイミングで走るようになる
- 今回はformatterとlinterによる整形を行う処理を走らせようにする

## ディレクトリ構成

- 以下のようなディレクトリ構成になっている
    - SPA構成にしたいのでfrontendとbackendを別々のディレクトリで作成している
- gitのリポジトリがあるディレクトリ(プロジェクトのルートディレクトリ)の直下に`.husky`を作成する

```bash
プロジェクトルート
├──.husky
│	 ├── _
│	 │   └── husky.sh
│	 └── pre-commit
├──frontend
├──backend
```

## 導入

- huskyとlint-stagedの導入方法

```bash
- コンテナ内
$ npm i -D husky lint-staged

- Mac側(プロジェクトルートディレクトリにて)
$ npx husky add .husky/pre-commit "cd frontend && npm run lint-staged"
```

- これでプロジェクト直下に`.husky`ファイルとその下に`pre-commit`ファイルができている状態になる
- ネットで調べてみると、古いバージョンなら`package.json`内で完結するように書かれている記事もあったが、どうやら最新のバージョンなどはpre-commitファイルを作る形になりそう

## package.jsonの中身

```json
"scripts": {    
    "prepare": "husky install",
    "lint-staged": "lint-staged",
  },
"devDependencies": {
	"husky": "^8.0.0",
	"lint-staged": "^13.0.0",
},
// ここに設定したコマンドが実行される
"lint-staged": {
    "*.{ts,vue}": [
      "eslint --fix"
    ],
    "*": "prettier -w -u"
}
```

## pre-commitファイルの中身

- 一回frontendディレクトリに移動して、`npm run lint-staged`を実行する
    - 理由としてはpackage.jsonがあるディレクトリがfrontendディレクトリになるため
    - ルートディレクトリで`npm run lint-staged`を実行すると、scriptがないと怒られる

```bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# commitするタイミングでfrontendディレクトリ直下にあるpackage.jsonの"lint-staged"を実行
cd frontend && npm run lint-staged
```

- エラーの時に以下のようにエラーが出てくれる
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323207/84b17303-acf0-32bb-3f13-4f597c1a8572.png)


- 成功したら以下のように上手くcommitできるようになる

![Untitled1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323207/24487520-37b2-15fe-8ba2-b6fffe106aa0.png)

## 勘違いしていた点

- docker環境なので、一回コンテナ内に入ってからlist-stagedコマンドを実行するのかと思っていた
    - マウントしているから、mac側からもコンテナ側からもpackage.jsonにはアクセスできる
        - つまり、`npm run lint-staged`とかはdockerもmacも両方の実行できる
    - husky君からすれば、docker環境とかは特に関係ない
- 以下のように書いてしまい、`current directory is not a git directory!`というエラーが出て、2時間くらい時間を取られた
    - 調べても全然出てこなくて困った
    - 仕組みを知っておくのは大事

```bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# frontendのコンテナ(nodeコンテナ)に入ってからnpm run lint-stagedを実行する必要があるのかと思っていた
docker compose exec node npm run lint-staged
```

## lint-stagedのタイミングでtsかvueの片方しか認識されない
- 以下の書き方を見てください
```json:package.json
"lint-staged": {
  "*.{vue, ts}": [
    "eslint --fix",
    "prettier --write"
  ]
}
```
- 特に問題ないかと一見見えますが、これだと`vue`ファイルのみしか認識されません。
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323207/f7c632ed-1d87-4574-75e8-8167a6ee0d99.png)

- この原因としては、`"*.{vue, ts}":`の部分で、vueとtsの間にスペースが入ってしまっていることです。
    - スペースを取り除いてあげるとts側も正常に認識されます。
```json:package.json
"lint-staged": {
  "*.{vue,ts}": [
    "eslint --fix",
    "prettier --write"
  ]
}
```
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323207/2b6fb025-46ea-4b01-ee5d-b9b93e7fe604.png)



- jsonの書き方を熟知している人ならこういうミスはないのかもしれないですが、個人的には分かりづらいエラーでしたので、どなたかの助けになれば幸いです。


## 参考記事

- [husky を v4 → v7 にアップグレードしたら pre-commit ができなくなった](https://zenn.dev/luvmini511/articles/a47b1aa0310d1a)
- [【husky】モノレポにhuskyを導入する【ESLint】【Prettier】](https://qiita.com/P-man_Brown/items/502247a8b8a81fecc696)
- [lint-staged/huskyを使ってコミット時やプッシュ時にコマンドを自動で発火するようにしよう！](https://qiita.com/miruon/items/fc344ea0a489cf9252d5)
- [husky + lint-staged を動かしたメモ@2021年7月](https://zenn.dev/seya/articles/c908d88df0a587)
- [husky v6 のインストール方法と使い方。lint-staged も導入して、品質を保とう](https://fwywd.com/tech/husky-setup)