top of page

おそうじ完了:GitHubのキャッシュをようやくちゃんと使えるようになりました 🧹

執筆者の写真: Marcel Dütscher
Marcel Dütscher
7月27日
読了時間: 5分

前回の技術記事では、ビルドとチェックのパイプラインに本当は何がかかっているのかを測りました。わかったのは、お金ではなく、待ち時間と保存容量だということでした。その記事は「おそうじの作業は計画してあるけれど、まだ終わっていない」で締めくくっていました。ところが、思ったより早く進みました。今日のお昼の時点で、メインブランチに入っています。数字をご紹介します。


まず結果から。 リポジトリのキャッシュ使用量は、63エントリで5.32GBだったのが、13エントリで2.46GBになりました。以前はプルリクエストのたびに走っていたC#のセキュリティ解析は、そこでは4分半から4秒になりました。それでいて、公開されるものはすべてチェックしています。みなさんを守るチェックは、どれもひとつも減らしていません。


簡単に言うと、キャッシュって何のためにあるの? ビルドは毎回、まっさらな空のマシンで始まります。毎回ゼロから始めなくてすむように、途中の結果を保存しておけます。次のときは、作り直すかわりにそれをダウンロードします。そのための領域がリポジトリごとに10GBもらえます。いっぱいになると、GitHubはいちばん長く使われていないものから消します。そして、まさにそこが私たちの問題でした。領域は埋まっていたのですが、間違ったものでふさがっていたのです。


間違い1:プラットフォームのないキー。 Unityはビルドのときに、巨大な中間フォルダを作ります。これを使うビルドは、Windows、Linux、macOS、WebGLの四つで、それぞれ自分用が必要です。Windowsのビルドだけが、キャッシュキーにプラットフォームの印がありませんでした。そのため、最初に見つかったエントリ、つまりWebGLのものと一致してしまいました。1.7GBがダウンロードされ、Unityはそれを正しく「ここのものじゃない」と見抜いて、最初からインポートし直しました。ログを見ると、インポートが85秒ではなく257秒かかっていました。キーはLibrary-Windows-になり、この怪現象は終わりました。


間違い2:だれも保存していなかった。 もっと恥ずかしい発見です。四つのビルドはどれも、まじめに中間フォルダを復元しようとしていましたが、それを書き込むワークフローは、ひとつもありませんでした。存在した唯一のエントリは、手で起動するツールから来たものでした。つまり、プロジェクトでいちばん大事なキャッシュは、偶然に維持されていたのです。🙈 今は、ちゃんと意図して書き込まれます。


容量を節約できた決め手:クリティカルパスだけが大事。 四つのプラットフォームすべてをキャッシュするのが、ありがちな手でしょう。でも、実際のリリースの時間を見ると、それがむだだとわかります。四つのビルドは同時に始まり、Windowsは11分で、LinuxとmacOSは13.7分で終わり、WebGLは31.6分で終わります。WebGLが動いているあいだは、ほかはどのみち待っています。だから、待ち時間を縮めるのはWebGLのキャッシュだけです。ほかの三つは、10GBの予算のうち約4.5GBを使うのに、縮まる時間はゼロ分です。そこで、キャッシュするのはきっかり一つだけにしました。


間違い3:Dockerが残りを食べていた。 サーバーイメージをビルドするとき、これまではすべての中間レイヤーがキャッシュとして保存されていました。24エントリで約3.27GB、予算全体の64%で、プッシュのたびに更新されていました。この大量のデータが、本当に大事なUnityのキャッシュを毎回押し出していたのです。今は最終ステージだけを保存し、四つのイメージそれぞれが自分の名前空間をもっています。以前は同じ名前空間を共有して、お互いを追い出し合っていました。3.27GBは、約150MBになりました。


セキュリティ解析:意味のあるところでチェックする。 セキュリティの穴を探すGitHubのツールCodeQLは、時間をいちばん使っていたものの第二位でした。8日間で230分で、そのほとんどがC#の部分です。解析のためにプロジェクト全体をビルドし直し、しかもプルリクエストのたびでした。今は、メインブランチへのマージのときと、週に一度、フルで走ります。プルリクエストでは、速いチェックだけを行います。変更後に測ると、プルリクエストでは4秒、メインブランチでは変わらずたっぷり4分でした。実際にみなさんに届くコードの行は、ちゃんとすべてチェックされています。ただ、三重にはやらないだけです。


積み重なる小さなこと。 .NETのパッケージも、人が待つ経路でだけですが、キャッシュするようになりました。他のプロセッサ向けのエミュレーターは、本当にそのためにビルドするときだけセットアップします。起動したてのマシンでは何もすることがないのに、ビルドのたびに最大1.4分もかかっていたクリーンアップのコマンドは、なくなりました。そして、リリースビルドの中間ファイルは、90日ではなく7日で消えるようになりました。合計7.4GBにもなる703個がたまっていたのです。


あえてやらなかったこと。 自分たちの分析から出た二つの提案は、測ってみてからやめました。変更履歴に見栄えのいい一行として載せることはしませんでした。テストを二つの並列ジョブに分けても、得られるのはちょうど4秒でした(片方が2:54、もう片方が4秒です)。しかも必須のチェック名が変わってしまい、すべてのプルリクエストが永遠に「待機中」になってしまいます。リリース前の大きなテストの関門をとばしても、何も節約にはなりません。WebGLがまだビルド中のうちに、とっくに終わっているからです。何も得られず、安全網だけをなくす最適化は、最適化とは言えません。


そして、本物のバグが出てきました。 このおそうじの最中に、突然すべてのプルリクエストが時間制限で失敗しました。ひとつのテストが、120秒までのところ212秒もかかったのです。同じ実行で二番目に遅いテストは10.5秒でした。原因は、サーバーのエラー処理でした。壊れたHTTPリクエストを、きちんと閉じずにぶつっと切っていたのです。Linuxでは、システムがそうした接続を回収するのは2分ごとの掃除のときだけで、シャットダウンはそれを辛抱強く待っていました。Windowsでは出なかったので、ビルドサーバーでしか問題になりませんでした。今は、サーバーがそういう場合に正直なエラーコードを返し、自分で接続を閉じます。テストは20秒ほどで終わります。そして、本物のプレイヤーがそういうトラブルに出会っても、切断ではなく、わかりやすいエラーが返ります。CIのおそうじの日に、本番のバグが見つかるなんて、いい日です。🐛


こうしたことは、みなさんに直接は何も変えません。新しいブロックも、新しい動物もありません。ただ、「コーディング完了」から「みなさんがインストールできる」までの道のりを短くします。そして前回と同じ言葉を証明しています。まず測る、それから手を入れる。🚀

最新記事

すべて表示
新しいバージョンが2026.7.19で、0.9.2ではない理由 🗓️

今日アップデートする人は、バージョン0.9.1から2026.7.19にジャンプします。打ち間違いに見えますが、意図した決定です。バージョンの付け方を、「セマンティック」から日付ベースのバージョン(年.月.カウンター)に変えました。その理由をお話しします。 古い方式は、だれも聞かない質問に答えていました。 セマンティックバージョニング(0.9.1、1.2.3…)は、ソフトウェアライブラリの世界から来

 
 
月に1000回のビルド実行、そのどれにもお金はかかっていません ⚙️

まず訂正です。この記事の最初のバージョンでは、GitHubのビルド時間を使い切ってしまい、そのせいでProアカウントにアップグレードせざるをえなかった、と書いていました。それは間違いでした。ドキュメントを一目見ればわかったことです。公開リポジトリでは、GitHubのビルド時間は無料です。アーティファクトもキャッシュもです。うちのリポジトリは5月末から公開されているので、1分もお金を払ったことはあり

 
 
SignPathの答えはノーでした:Windows版はしばらく署名なしのままです

数日前、このブログでお知らせしましたね。Windowsインストーラーのコード署名証明書をもらうために、SignPath Foundationの無料オープンソースプログラムに申請した、と。その答えが届きました。結果は、ノーです。この開発ブログは、うまくいったことを祝うだけの場所ではなく、こういうプロジェクトが本当はどう進むのかを正直に伝える場所です。だから、このお知らせもここに書きます。 おさらい:

 
 

コメント


この投稿へのコメントは利用できなくなりました。詳細はサイト所有者にお問い合わせください。
bottom of page