この記事ではコミット時にJavaScriptプログラムをNode.js環境で走らせて、実行結果(process.exit(code)のcodeの値)によってコミットをさせない、させない理由の表記をする方法を紹介します。
使う主な技術はgit commitなどのgitコマンドに反応して色々やれる”Gitフック”とpackage.jsonでGitフック時の動作を定義できる”husky”です。
Git – Git フック
typicode/husky: Git hooks made easy 🐶 woof!
【Git】package.json上でコマンドとGitを連携させるためのhusky, lint-staged – 株式会社シーポイントラボ | 浜松のシステム開発会社
実装は次です。
package.jsonのhusky.hooks[pre-commit]にcommit直前に処理したいコマンドを記述します。次のコードならば、lint-stageが正常終了後にnode gitHooks/preCommit.jsが実行されます。
// package.json "husky": { "hooks": { "pre-commit": "lint-staged && node gitHooks/preCommit.js" } },
gitHooks/preCommit.jsには次の様にgit解析なりソースコード解析なりとルールを仕込みます。ルールに反した際はその旨のメッセージconsole.errorと異常終了を示すprocess.exit(1)を実行してフックを終わらせます。
// gitHooks/preCommit.js // gitのコマンドを実行 const childProcess = require('child_process'); const gitBranchStdOut = childProcess.execSync('git branch').toString(); // git branchで次の様な文字列が標準出力される // // * develop // master // // これの内 "* "から始まる行が現在のブランチを示す行。ここから正規表現で現在のブランチ名を抜き出す const currentBranchName = gitBranchStdOut.match(/^\* (.*)$/m)[1]; // 現在参照しているブランチがmasterであるならば if (currentBranchName === 'master') { console.error(''); console.error('masterブランチにcommitしようとしています'); console.error(''); process.exit(1); } // 現在参照しているブランチが特定の正規表現に一致しないならば const category = [ // 機能追加に合わせて適宜追加 'admin', 'user', 'post', ].join('|'); const branchRuleRegex = new RegExp(`^\\* (master|develop|feature-(${category})\\/-MY_PROJECT-\\d+)`, 'g'); if (! branchRuleRegex.test(currentBranchName)) { console.error(''); console.error('ブランチ名が命名規則に反しています。ブランチ名を変更してください'); console.error(`例: git branch -m ${currentBranchName} <新しいブランチ名>`); console.error(`ブランチ名の命名規則は次の正規表現です。${branchRuleRegex.toString()}`); console.error(''); process.exit(1); }
例のやり方の実行結果が次です。
例のやり方はdevlopやfeeturの様な誤字ブランチが作られず、後の検索性もよくなります。
このやり方の注意点として重い処理を書くと不便さが勝り出す点があります。特に危険なのがプロジェクトの成長に伴って実行時間が増えるテスト系統で、その中でもブラウザテストはとても耐えられません。テストの自動実行を総ざらいでする際はJenkins等の継続的インテグレーション関連のソフトを用いてなるべく開発者に関係のないマシン上で並行して実行させるのがよいです。
このやり方の応用でhuskyの対応しているGitフック(pre-pushなど)にコマンド実行が可能なスクリプト(PHP, Python, シェルスクリプトなど)を自由に設定できます。