core.hooksPathを使って、コミットするときに文章中の軽微なミスを検出する仕組みを考える

Blog

core.hooksPathを使って、コミットするときにtextlintを実行し、文章中の軽微なミスを検出するGit Hooksを作った。

This Git hook is pre-commit that to assist writing document by using core.hooksPath - chick-p/git-hooks-textlint
GitHub

このGit Hooksを利用すると、事前に定義したtextlintのルールに基づいて、絶対に修正したい用語を使っている場合はコミットを中断し、文脈で判断する必要がある場合はコミットするかを選ぶことができる。

背景

仕事でライティングをしているとき、製品名やサービス名をtypoしたりカタカナ語の長音の有無が揺れていたりといった軽微なミスをすることが多々ある。
そのようなミスは機械的に検出しやすいため、CI上でtextlintを動かして、Pull Requestのレビュー前に検出できる仕組みを構築している。
一方で、自分だけが良くしてしまうミスもある。たとえばページ内で類義語が揺れていたり、テクニカルライティングの技法として伝わりづらい表現を使ってしまったりすることがある。
こういった個人的にやらかしてしまうミスを、CI上で実行しているtextlintのルールファイルに反映することは心苦しく感じている。

実現したいこと

個人的なミスを検出する仕組みでは、次のことを実現したい。

  • プッシュする前にtextlintを実行することを忘れるため、コミットしてしまう前に気づきたい
  • 編集するコンテンツは複数のリポジトリに分かれているため、リポジトリごとに仕組みを管理したくない
    たとえば、textlintの実行環境やルールは各リポジトリで共有したい
  • 使わないと決めた用語を使っている場合はコミットを中断し、文脈で使うかを判断する必要がある場合はコミットするかを選べるようにしたい

実現方法

調べてみると、azuさんのsecretlint/git-hooksが参考になりそうだった。
この構成を参考にして、コミットしてしまう前にtextlintを実行する仕組みを作ることにした。

  • Git Hooksのpre-commitを使うと、プッシュする前にtextlintを実行できる
  • Git Hooksをcore.hooksPathに設定すると、スクリプトをリポジトリごとに管理する必要がない
    ただし、グローバルなGit Hooksは複数定義できないため、適用したいリポジトリにだけ--localオプションをつけてcore.hooksPathを設定する
    リポジトリ内に個別のGit Hooks(.git/hooks)が設定されているリポジトリの場合、先にリポジトリ内のGit Hooksを実行する
  • Dockerを使ってtextlintの実行すれば、textlintの実行環境やルールを共有できる
    私はNode.jsのバージョン管理ツールを使っているため、グローバルインストールすると、Node.jsのバージョンを切り替えるたびにインストールが必要になる

また、textlintでは、ルールごとにエラー結果をWarningにしてステータスコード0を返すことができる。
textlintのルールには、正規表現を使って特定のパターンを検出する、@textlint-rule-prh@textlint-rule/textlint-rule-patternというよく似た2つのルールがある。
このルールを使い分けて、それぞれ別のステータスコードを返すようにする。

  • @textlint-rule-prh:Errorとしてステータスコード1を返す
    使わない決めた用語を使っている場合のパターンを記載する
  • @textlint-rule/textlint-rule-pattern:Warningとしてステータスコード0を返す
    文脈で使うかを判断する必要がある場合はコミットするかを選べるようにする

類義語の揺れの検知には@textlint-ja/textlint-rule-no-synonymsを使うことにした。
どの用語を使うかは文脈で判断する必要があるため、Warningを返すようにした。

利用イメージ

Docker上でtextlintを実行するため、事前にDockerを起動しておく。

コミットするタイミングで、prh.ymlで定義したパターンに一致する場合は、エラーで止める。
スクリーンショット:エラーでコミットが中断されている

textlint-rules-patternpatternsで定義したパターンに一致する場合は、コミットするかどうかを尋ねる。
スクリーンショット:エラーでコミットが中断されている

Dockerイメージのバージョンが同じ場合は、次回起動時にはDockerイメージはビルドされない。

所感

  • 自分がやってしまいがちなミスのチェックリスト代わりにはなりそう。
    ただし、チーム内で合意で決まったルールは、チームのtextlintのルールファイルに反映したほうが良い。
  • ルール設定ファイルを変更した場合、Dockerイメージのバージョンを上げる必要がある。
    この辺は自動化できるのだろうか。Dockerは手探りで勉強しているのでわからない。