自動生成コマンドの叩き忘れをCIで検知する
とあるファイルAを変更した時に、自動生成コマンドを使って変更後の内容に基づいて別のファイルBを変更するものがあったとする。
この時ファイルAを変更しても自動生成コマンドを叩き忘れればファイルBは変更されない。
これをCI上で検知するためのGitHub Actionsを書いたのでまとめておく。
今回はCI上でエラーにするだけでなく、PR上にコメントでメッセージを出せるようにもした。
差分があった場合はこんな感じでコメントを発行してくれるようになった。
改めて何がしたいかを記載する
ファイルAを変更後、scripts
にある自動生成コマンドを叩くとファイルBが変更されるとする
このgenerate
コマンドを叩き忘れるとファイルBが変更されない。
これをCI上で検知したい。
方針としてはシンプルで、CI上でgenerate
コマンドを叩いてそれによって差分があるかどうかを検知できればよい。
差分検知はgit diff
を使えばよさそう。
問題はgit diff
を行った時に差分があった場合はCIを落としたいのでエラーにする必要がある。
オプションを見てみると--exit-code
なるものがあって、これを付与すると意図した通り差分があった場合はエラーにしてくれる。
ここまでを一旦CIとして記述してみると以下の様になった。
(普段はyarn
を使っているが、後に記述する事情からここではpnpm
を利用している)
generate
コマンドを叩いてからgit add
してgit diff --cached --exit-code
で差分があった場合はエラーにしている。
そのままgit diff
せずにわざわざgit add
している理由は、既存のファイルを編集した場合のみだけでなく、新しく作成したファイルや削除したファイルに関しても差分検知の対象とする必要があったため。
CI上でエラーにするだけならこれで完成。
CIが落ちた時には実際にgenerate
コマンドを叩いて出てきた差分をコミットする必要がある。
これをPR上のコメントで表示させることでユーザーに何をすべきかを提示する様にしたい。
PR上にコメントを出すのはgithub-script
を使用する。
エラーになった際にこの処理を行う必要があるので、エラーでも処理を続ける必要がある。
これを実装すると以下の様になった。
6行目でdiffを検知した際にエラーだったとしても処理を続けるようにしている。
その後コメントするためのscript
を実行している。
この内容は後述する。
最後にdiffがあった場合はCIをちゃんと落とすためにexit 1
でコード1で終了する。
肝心のscript部分がこちら。
引数として処理に必要なgithub
とcontext
を受け取る。
それに加えてisSuccess
というboolean
を受け取っていて、差分があった(=isSuccess
がfalse)場合は以下のコメントをPR上に発行し、差分がなくなった(=isSuccess
がtrue)場合はPR上のコメントを消すようにしている。
Uncommitted changes were detected after runnning generate
command.
Please run pnpm run generate
to generate/update the related files, and commit them.
内容は若干違うが、差分があった場合はこんな感じでコメントをしてくれるようになった。
github-script
の実装はTSで書かれていて型が付いている。
GitHub Actions上で記載する部分はテンプレートとして書かないとなので型の恩恵は得られないが、今回の様にスクリプトファイルに切り出してそれを実行する場合はスクリプトファイルの方はTSにできる。
ということでやってみた。
型の内容は大元のコードを読んでそれと同じものにした。
github-script
でtsファイルは実行できなさそうだったので、上記のTSファイルは事前にトランスパイルしてから実行する必要があるため、以下のstepを追加。
これでTSファイルを用意しておけばトランスパイルしたJSファイルを実行できる。
実は今回のこのCI、fakerというライブラリのissueでこの機能が欲しいというものがあったので、実際にPRを作ったものである。
(このライブラリがpnpmを使っているため、今回はpnpmで記述した)
Add CI steps to test execution of generate scripts · Issue #813 · faker-js/fakerClear and concise description of the problem We need to add CI steps for the execution of some generate scripts, so we guarantee that these will not break Suggested solution Add steps Alternative N...github.com
このPRがマージされた後、実際にこのCIによって差分を検知できたらしく、メンテナーの方からフィードバックをもらえた。
これがめちゃくちゃ嬉しくて本当にやってよかったなと思えた!
I just want to report you back I LOVE THIS NEW FEATURE 😍
infra: move the check-code-generation job to pr.yml by sunadoi · Pull Request #1419 · faker-js/fakercheck-code-generation CI fails in main branch.
This PR Moves the job to pr.yml and run it only for PRs and not main.
#1405 (comment)github.com
普段から使用しているライブラリに対して役立つ機能を実装できたので、本当にやってよかった!
以前もfakerにPR出してマージされたことはあったが、めちゃくちゃ簡単な修正だったのであまりやった感なかった。笑
今回はちゃんとOSSコントリビュート出来たと思えたのと、PR上で色々やりとりしてかなり勉強になった。
実装したCIもわりと汎用性あって別の箇所でも使えそうだなと思えたので、今後機会があれば使っていこうと思う。