0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

lefthookでコミットメッセージの品質を確保したいですわね

Posted at

前略

皆様ごきげんよう。
コミットメッセージにも一貫性を持たせたいですわよね?(圧)
私はいつも、下記の記事のコミットメッセージルールを参考に開発しておりますの。

ルールを守ると、誰が見てもどんな変更かが伝わって幸せになりますわ。
ただ、毎回手動でルール準拠か確認するのはしんどいですわね???
┏( .-. ┏ ) ┓
そんなあなたにおすすめするのが lefthook ですわ‼

lefthook を使うと、コミット前や push 前といった任意のタイミングで好きな処理を挟めますの。

例えば――

この「ルールチェック」を自動化できますわ。
今回は 正規表現 を用いてチェックしていきますの (๑`·ᴗ·´๑)


導入編

今回の検証プロジェクトは React + TypeScript(Node環境)ですわ。
もちろん他環境でも大丈夫。私が個人的に作っているプロジェクトʕ•͡ω•ʔで試した流れのままご紹介しますわね。

公式ドキュメントどおり、導入はこんな感じですわ(npm はあまり使いたくなくても今回は素直に…)。

npm install lefthook --save-dev

開発環境(devDependencies)に入れるスタイルですわね〜。
ここで注意ポイント‼

lefthook は Git フックの管理ツール。つまり Git リポジトリが前提 ですわ。
git 環境がない場合は、まず初期化なさいませ。

git init

では早速、lefthook install を実行してまいりますわ。

koki@YamamotoK test-shell % lefthook install
zsh: command not found: lefthook

は?動かんやんけ ウザ━━━━(´Д`)━━━━イ
……落ち着いて欲しいですわ。
原因は lefthook をローカル(devDependency)に入れただけで、シェルの PATH に載っていない から、でございますの。
そこで、package.json の npm script から呼び出すようにいたしましょう(npm スクリプト内では node_modules/.bin が自動で PATH に入りますの)。

{
  "scripts": {
    "prepare": "lefthook install"
  }
}

これで npm run prepare を実行すれば、Git フックがインストールされますわ(lefthook.yml は通常は自分で用意します。環境によっては雛形が生成される例もありますが、公式の基本導線は「自分で作成→install」ですの)。(npm, lefthook.dev)

参考:lefthook.yml はリポジトリ直下に置きます。lefthook-local.yml というローカル専用設定も使えますわ。(lefthook.dev)


# lefthook.yml(サンプル)
# EXAMPLE USAGE:
#   See: https://lefthook.dev/configuration/
#
# pre-push:
#   jobs:
#     - name: packages audit
#       tags: [frontend, security]
#       run: yarn audit
#
# pre-commit:
#   parallel: true
#   jobs:
#     - run: yarn eslint {staged_files}
#       glob: "*.{js,ts,jsx,tsx}"
#
#  ...(以下略)

ではざっくり解説しますわ。
Git には Git フック と呼ばれる、特定のアクションでスクリプトを実行できる仕組みが用意されていますの。(Git)

  • pre-push フックgit push 実行時、リモート参照の更新後・オブジェクト転送の前に実行(ここで弾くのは推奨ですが、コミットを書き換えるのは筋が悪いですわ)。(Stack Overflow)
  • pre-commit フック:コミット作成前に実行(この段階ではまだメッセージ編集前ですわ)。(Reddit)
  • prepare-commit-msg フック:デフォルトメッセージ生成直後、エディタが開く直前に実行。(Git)
  • commit-msg フック:書かれたコミットメッセージ(ファイルパスが引数)を検証する段階ですわ。(Git)

つまり、lefthook.ymlpre-〇〇 に処理を記述すると、任意のタイミングで好きなチェックを挟める、という寸法ですわ。

それでは本題にまいりますわ ヾ(๑╹ꇴ◠๑)ノ”


正規表現にすべてを賭けろ

今回は commit-msg のタイミングで、コミットメッセージがフォーマットに合っているか 正規表現 で検証しますわ。

正規表現は情報工学徒ならきっと履修しておりますし、下の記事でもわかりやすく学べますの(基礎の確認にどうぞ)。

やりたいことはこうですわ:

プレフィックス検証(正規表現)

  • 許可:feat: fix: docs: style: refactor: perf: test: chore:

  • 流れ

    1. ユーザーのコミットメッセージを取得
    2. 先頭がパターンどおりか正規表現で確認
    3. 違ったらエラーで中断

つまり――

⭕️ "feat: 〇〇を修正した"
❌ "〇〇を修正した"

のように「頭文字+コロン+半角スペース」で始まる場合のみ許可、にいたしますわ。

では、ルート直下に scripts フォルダを作り、その中に check-commit-message.sh を用意しますわね。

├── scripts
│   └── check-commit-message.sh
├── src
│   └── ...(省略)

内容は次のとおりですわ:

#!/bin/bash

# 正規表現によるプレフィックス検証
# 許可: feat|fix|docs|style|refactor|perf|test|chore
allowed_prefixes="^(feat|fix|docs|style|refactor|perf|test|chore): "

# Git から渡されるコミットメッセージファイルのパス
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")

echo "コミットメッセージを確認中..."
echo " -> ${commit_msg}"

# [[ 文字列 =~ 正規表現 ]] でマッチ判定
if [[ "$commit_msg" =~ $allowed_prefixes ]]; then
  echo " コミットメッセージのフォーマットは問題ないです"
  exit 0
else
  echo "--------------------------------------------------"
  echo "✖ [エラー] コミットメッセージのプレフィックスがルール違反"
  echo "メッセージの先頭は、以下のどれかで始めてください"
  echo "  feat: (新機能)"
  echo "  fix: (バグ修正)"
  echo "  docs: (ドキュメント)"
  echo "  style: (コードスタイル)"
  echo "  refactor: (リファクタリング)"
  echo "  perf: (パフォーマンス改善)"
  echo "  test: (テスト追加・修正)"
  echo "  chore: (ビルド関連など)"
  echo "例: feat: 新しいログイン機能を追加"
  echo "--------------------------------------------------"
  exit 1
fi

メモ:bash scripts/... と明示的に bash で実行しているので実行権限はなくても動きますが、気持ちよく使うなら chmod +x scripts/check-commit-message.sh しておくのも良き、ですわ。

次に、lefthook に反映しますわ。

# lefthook.yml
commit-msg:
  commands:
    check-message:
      run: bash scripts/check-commit-message.sh {1}
  • commands: 実行するコマンド群
  • check-message: 任意のコマンド名
  • run: 実行コマンド本体
  • {1}: hook から渡される「コミットメッセージファイルのパス」をシェルへ引き渡しますの

これで コミットのたびに自動チェック が走りますわ‼


実行してみる

適当なファイルを「おーきーどーきー」というメッセージでコミットしてみますわ。

> git -c user.useConfigOnly=true commit --quiet --allow-empty-message --file -
╭───────────────────────────────────────╮
│ 🥊 lefthook v1.12.3  hook: commit-msg │
╰───────────────────────────────────────╯
┃  check-message ❯ 

コミットメッセージを確認中...
 -> おーきーどーきー
--------------------------------------------------
✖ [エラー] コミットメッセージのプレフィックスがルール違反
(中略)
exit status 1

( ´,_ゝ`) しっかり弾かれていますわね。

ルールどおりの頭文字を付けて再実行すると――

git commit -m "feat: おーきーどーきー"
╭───────────────────────────────────────╮
│ 🥊 lefthook v1.12.3  hook: commit-msg │
╰───────────────────────────────────────╯
┃  check-message ❯ 

コミットメッセージを確認中...
 -> feat: おーきーどーきー
 コミットメッセージのフォーマットは問題ないです

✔️ check-message (0.02 seconds)
[main (root-commit) 9a57928] feat: おーきーどーきー
 1 file changed, 70 insertions(+)
 create mode 100644 README.md

キタ━(゚∀゚)━! というわけですわ。


まとめ

追加したい規約 に対して、簡単な シェルスクリプト を用意し、lefthook.yml の該当フックにぶら下げれば、コミット時に自動チェックで“舞えます”わ。
まずは commit-msg での プレフィックス検証 から始め、必要に応じて pre-commit で Lint/Format、pre-push でテスト等も併用していくのがおすすめですわ。(lefthook.dev)


おまけ

  • commitlint を Lefthook から呼び出せば、複雑なルールも楽に運用できますの。(GitHub)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?