エンジニア不在時に対応できないSlackビルドの失敗
梁瀬貞裕氏:「動かないコードをマージさせないためのコンパイルエラー検知くんをGitHub Actionsで作った話」という内容で発表します。
まず、自己紹介をします。sadaと申します。Graffity株式会社所属、新卒1年目のクライアントエンジニア兼ARエンジニア兼CI/CDエンジニアです。だいたい配分が6対3対1で、今日はその配分1のCIエンジニアとしてお話しします。
新卒1年目なのですが、実はインターンなども含めるとGraffityには3年くらい在籍していて、「Leap Trigger」というスマホ向けARシューティングバトルゲームを開発、運営中です。
ここからが本題です。まず開発経緯ですが、弊社では「Slack」でJenkinsおじさんにビルドコマンドを投げる仕組みを使っています。
下の画像のような流れで、よくあるタイプのSlackからHubotでコマンドを受け付けて、Jenkinsに受け渡して、Unityがビルドするようになっています。
Slackビルドはエンジニア以外も使うので、エンジニアがミーティング中でも、担当者が休みでもビルドが行われます。セキュリティの関係上、誰でもJenkinsにログインできるようにはしたくなかったので、ビルドが失敗したことしかSlackには通知されません。このように、エンジニアが不在の時にビルドを失敗すると対応できないことから、開発を考えました。
ビルド失敗の一番の原因「コンパイルエラー」をチェックする仕組み
そこで、ビルドを失敗する原因で一番多かった、コンパイルエラーのコードを本流のブランチにマージさせない仕組みを作成しようと考えました。GitHubのプルリクエストにコミットがPushされるたびに、コンパイルエラーかどうかをチェックするという、わりと簡単な仕組みになっています。下の画像が、だいたいの図です。
実装に使用したものは、UnityとGitHub Actionsです。GitHub Actionsでは、self-hosted runnerという仕組みを使っています。
UnityとGitHub Actionsの実装
Unityの実装編です。バッチモードでUnityのプロジェクトを開いて、コンパイルエラーなどを起こしていたら、exit1で終了する仕様です。今回は使用しませんが、UnityEditorで開いているので、ついでに.csprojの依存性なども解決してくれます。
GitHub Actionsの実装編です。GitHub Actionsは、大雑把に言うと自動化ツールです。GitHubに付属するツールなので、Pushされる、Issuesが来る、プルリクエストのコメントが付く、などのGitHub特有のイベントをトリガーにできます。ほぼ同様のツールに、GitLab CIなどがあります。
self-hosted runnerとは、GitHub Actionsが実行される仮想マシンを自前のPCで実行できる公式のツールです。
なぜself-hosted runnerを使っているかというと、GitHub ActionsのDockerでもUnityは使用できるんですが、少しライセンス処理が面倒でプロジェクトがかなり重たいため、毎回Pullしてインポートしていると、けっこう時間がかかります。なによりプライベートなリポジトリのため、GitHub Actionsではお金がかかってしまうし、ちょうどJenkinsに使っているMac miniがある、などが理由でした。特に、チーム開発や開発規模が大きくなると、前者2つが大きな問題になりがちです。
self-hosted runnerの注意点として、任意コードを実行できるため、絶対にパブリックなリポジトリで設定しないようにしてください。それをしてしまうと、悪意のある人が踏み台サーバーにしたり、仮想通貨を掘ったりしてきます。
また、実行速度はホストPC依存なので、Mac Proなどに入れると、けっこう速くなります。
GitHub Actionsのymlのファイルの全体像
ここからは、GitHub Actionsのymlのファイルの説明です。だいたい全体像がこんな感じで、大きく3つに分かれています。1つずつ見ていきます。
まず、この部分は実質おまじないみたいなものです。初期設定や実行する環境の設定、Gitのブランチにチェックアウトしています。
次のステップです。この部分は、Unityをバッチモードで開いているだけです。UNITY_PATHはUnityのPATHなので、上のほうで環境変数に指定してもいいし、直書きしてもいいと思います。
GITHUB_WORKSPACEは、GitHub Actionsで提供されている環境変数の1つで、そのリポジトリの直下のPATHを示しています。
この項で、GitHubのプルリクエスト上にコメントしています。
このsecrets.GITHUB_TOKENは便利なアクセストークンで、これを使うとGitHub Actions専用のBotを使用できます。この画像のように返してくれます。
このちょっと長めのgithub.event.pull_request.comments_urlは、イベントが発火されたプルリクエストのコメントURLです。このURLを使用して、プルリクエストにコメントするAPIをPOSTで実行しています。
github.actorは、イベントを開始した時にコミットした人です。注意点として、ユーザー名からアットマークが省かれているので、メンションする時はアットマークを付ける必要があります。
また、github.shaはその名のとおり、開始されたイベントのコミットハッシュです。URLを特定するために使用しています。
これらを全部実装すると、この画像のようなものがプルリクエストのコメントに表示されます。あとはSlackにも投げれば、コンパイルエラー検知くんの出来上がりです。
資料を公開するので、GitHub Actions、GitHubのページを参考にしてもらえるとありがたいです。
コンパイルエラー検知くんを導入した結果
次に効果についてです。2020年10月くらいに導入してみました。このチェックは、だいたい1分前後で終わります。ただ、けっこうUnityのインポート時間に左右されるので、30秒だったり、2分だったり、マチマチです。
なにも設定していない場合は、Standaloneプラットフォームで開きます。画像の圧縮設定などをしていないことが多いので、インポートは比較的早くやってくれます。
その結果、ビルドを失敗することはかなり減りました。しかし、アセットバンドル関連や、using Editorなどが入っていた時のビルド中の失敗は検知できないので、現在新バージョンを構想中です。
また、コンフリクトの解決後など、コンパイルエラーのコミットをPushしてしまった時やコミットを忘れたファイルがあった時にも、気がつけるようになりました。ちなみに、実際のコンパイルエラーの原因は、コミット忘れ、コンフリクトの解決後、そもそもコンパイルエラーのコードをあげてしまった、の順に多かったです。
最後に、コンパイルエラー検知くんはこんなふうに元気に動いていました。さっき言っていた、Slackに投げるものを実装した感じです。
これで発表を終わります。ご清聴ありがとうございました。