【commitlint】commitlintとcommitizenの導入方法【commitizen】

## commitlintの導入

https://github.com/conventional-changelog/commitlint

パケージマネージャーはyarn3を使用しています。
以下yarnを使用する前提で記述します。
### インストール
以下のコマンドを実行しcommitlintをインストールします。

```:ターミナル
$ yarn add -D @commitlint/{config-conventional,cli}
```

### commitlintの設定をする
commitlintの設定をするために`.commitlintrc.json`を作成します。
内容は以下のようにします。
`"rules"`以下は設定を変更したい場合に記述してください。`"@commitlint/config-conventional"`の設定をそのまま使用する場合には`"rules"`以下は不要です。
```.commitlintrc.json
{
  "extends": ["@commitlint/config-conventional"],
  "rules": {
    "header-max-length": [2, "always", 72],
    "type-enum": [
      2,
      "always",
      [
        "build",
        "ui",
        "ci",
        "docs",
        "feat",
        "fix",
        "perf",
        "refactor",
        "revert",
        "format",
        "test"
      ]
    ]
  },
  "prompt": {
    "messages": {
      "skip": "'Enterでスキップ'",
      "max": "最大%d文字",
      "emptyWarning": "必須事項です",
      "upperLimitWarning": "最大文字数を超えています"
    },
    "questions": {
      "type": {
        "description": "変更の種類を選択する",
        "enum": {
          "build": {
            "description": "ビルドシステムや外部依存に関する変更",
            "title": "Builds"
          },
          "ci": {
            "description": "CIの設定ファイルやスクリプトの変更",
            "title": "Continuous Integrations"
          },
          "chore": {
            "description": "補助ツールの導入やドキュメント生成などソースやテストの変更を含まない変更",
            "title": "Chores"
          },
          "docs": {
            "description": "ドキュメントのみの変更",
            "title": "Documentation"
          },
          "feat": {
            "description": "新機能の追加",
            "title": "Features"
          },
          "fix": {
            "description": "バグの修正",
            "title": "Bug Fixes"
          },
          "format": {
            "description": "動作に影響を与えないコードの書式などの変更",
            "title": "Format"
          },
          "perf": {
            "description": "パフォーマンス向上を目的としたコードの変更",
            "title": "Performance Improvements"
          },
          "refactor": {
            "description": "新機能追加でもバグ修正でもないコードの変更",
            "title": "Code Refactoring"
          },
          "revert": {
            "description": "コミットの取り消し",
            "title": "Reverts"
          },
          "test": {
            "description": "テストの追加や変更",
            "title": "Tests"
          },
          "ui": {
            "description": "スタイリングの追加や変更",
            "title": "UI"
          }
        }
      },
      "scope": {
        "description": "変更範囲を記述する"
      },
      "subject": {
        "description": "変更内容を概括する"
      },
      "body": {
        "description": "変更内容を詳述する(body:最大100文字)"
      },
      "isBreaking": {
        "description": "破壊的変更はあるか"
      },
      "breakingBody": {
        "description": "破壊的変更がある場合は必ず変更内容を詳説する"
      },
      "breaking": {
        "description": "破壊的変更内容を詳述する(footer:最大100文字)"
      },
      "isIssueAffected": {
        "description": "未解決のissuesに関する変更か"
      },
      "issuesBody": {
        "description": "issuesをcloseする場合は必ず変更内容の詳説する"
      },
      "issues": {
        "description": "変更内容の詳説とissue番号を記載する(footer:最大100文字)"
      }
    }
  }
}
```

### huskyの設定をする
huskyで`git commit`した際に自動でlintするようにします。
以下のコマンドを実行します。
```:ターミナル
$ yarn add husky --dev
$ yarn husky install
$ npx husky add .husky/commit-msg 'yarn commitlint --edit "$1"'
```
すると`.husky/commit-msg`が作成され、内容は以下のようになっています。
```.husky/commit-msg
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

yarn commitlint --edit "$1"
```

### 動作確認
`git commit`して正常に動作するか確認します。
以下のようにエラーが出れば正常に動作しています。
```:ターミナル
$ git add .
$ git commit -m "test"
⧗   input: test
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

✖   found 2 problems, 0 warnings
ⓘ   Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky - commit-msg hook exited with code 1 (error)
```

## commitizenの導入

https://github.com/commitizen/cz-cli

### インストール
まずcommitizenをインストールします。
あわせてcommitizenの設定に`.commitlintrc.json`を使用できるように`@commitlint/cz-commitlint`もインストールします。


https://www.npmjs.com/package/@commitlint/cz-commitlint

```
$ yarn add -D @commitlint/cz-commitlint commitizen
```

### commitizenの設定をする
commitizenの設定をするをします。
`package.json`に以下を追記します。
```package.json
{
  "scripts": {
    "commit": "git-cz"
  },
  "config": {
    "commitizen": {
      "path": "@commitlint/cz-commitlint"
    }
  }
}
```

これでcommitizenが`.commitlintrc.json`の設定で使用できます。

### 動作確認
`yarn commit`して動作確認をします。
以下のように表示されて対話形式でコミットメッセージを作成することができれば正常に動作しています。
```:ターミナル
$ git add .
$ yarn commit
cz-cli@4.2.4, @commitlint/cz-commitlint@17.0.0

? 変更の種類を選択する: (Use arrow keys)
❯ feat:       新機能の追加
  fix:        バグの修正
  docs:       ドキュメントのみの変更
  refactor:   新機能追加でもバグ修正でもないコードの変更
  perf:       パフォーマンス向上を目的としたコードの変更
  test:       テストの追加や変更
  build:      ビルドシステムや外部依存に関する変更
```
以下のようなエラーが発生した場合には`inquirer`をインストールします。
```:ターミナル
$ git add .
$ yarn commit
@commitlint/cz-commitlint tried to access inquirer (a peer dependency)but it isn't 
provided by your application; this makes the require callambiguous and unsound.

<以下略>
```

```:ターミナル
$ yarn add -D inquirer
```

### huskyを設定する
こちらもhuskyで`git commit`した際に動作するようにします。
以下のコマンドを実行します。
```:ターミナル
$ npx husky add .husky/prepare-commit-msg "exec < /dev/tty && yarn cz --hook || true"
```
すると`.husky/commit-msg`が作成され、内容は以下のようになっています。
```.husky/commit-msg
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

exec < /dev/tty && yarn cz --hook || true
```

### 動作確認
`git commit`して正常に動作するか確認します。
以下のようにエラーが出れば正常に動作しています。
```:ターミナル
$ git add .
$ git commit
cz-cli@4.2.4, @commitlint/cz-commitlint@17.0.0

? 変更の種類を選択する: (Use arrow keys)
❯ feat:       新機能の追加
  fix:        バグの修正
  docs:       ドキュメントのみの変更
  refactor:   新機能追加でもバグ修正でもないコードの変更
  perf:       パフォーマンス向上を目的としたコードの変更
  test:       テストの追加や変更
  build:      ビルドシステムや外部依存に関する変更
(Move up and down to reveal more choices)
```