self-hosted runnerで無限CIのカバー画像
self-hosted runnerで無限CI
2026/7/13
このエントリーをはてなブックマークに追加

最近はIssueをAIに拾わせて調査させて直させてPRまで出させて、条件が揃えば自動でマージする、というループを無限に回しています。便利なんだけど、これがGitHub ActionsのCIに完全依存していて、無料枠を使い切るとループごと止まってしまう。そんな悩みごとを解決してくれるのはやはりオンプレ。

オンプレは全てを解決する。

self hosted runnerを動かすことにしました。

開発サイクルとボトルネック

今のAI開発ループとそのボトルネックはこんな感じ。

開発サイクルとボトルネック

CIがgreenにならないとPRはマージされない設計にしているので、CIが1つ止まるだけでループ全体が止まる。AIがどれだけ元気にIssueを拾って直しても、CIの無料枠が尽きた瞬間に全部渋滞する。これがずっと気になっていた。

self-hosted runner

自宅にはもういろんなサービスをGitOpsで動かしている。だったらself-hosted runnerもそこに住まわせればいいじゃん、ということでActions Runner Controllerを入れることにした。KubernetesのCustom Resourceとしてrunnerを管理してくれる仕組みで、既存のArgoCDにHelm chartを1つ足すだけで済むのがありがたい。

認証はGitHub Appにした。個人アカウントなので組織単位のrunner共有みたいな機能は使えないんだけど、Appを作っておけばインストールするリポジトリを増やすだけで他のリポジトリにも使い回せる。地味に楽。

これで開発ループはこう変わりました。

修正後の開発サイクル

無料枠切れで詰まっていたCIの実行が自宅のRunner Podに移っただけで、ジョブディスパッチも自動マージも変わらず素通りするようになった。無料枠を気にする必要がなくなったので、ループはもう止まらない。

Runnerの設計

Runnerのpodはジョブが1つ来るたびに使い捨てられる仕組みになっている。レプリカを増やしてキャッシュ用のボリュームを持たせようとすると、みんなで1つのボリュームを取り合ってスケジューリングが詰まってしまう。うーん、どうしようかな。と考えた末、レプリカ数は1固定にすることにした。その代わりキャッシュ(cargoのレジストリとビルド成果物、あとuvのキャッシュ)は永続化ボリュームに逃がして使い回す。並列実行は諦めたけど、無料枠が尽きてCIが1個も動かないよりはマシ。

辛くなってきたら水平スケール出来るようになにか考えるかも。

リソースは普段ほとんど遊んでいるので、requestは絞って、実際にジョブが来た時だけGitHub-hosted相当(2 vCPU/7GB)までバーストできるようにしている。

これが
スクリーンショット 2026-07-13 20.48.07.png

こう
スクリーンショット 2026-07-13 22.12.56.png

そこそこの速度でちゃんと動いてくれるから今のところ不満ないかも
(CI転けてるけど)

今後

キャッシュが実際にどれくらいビルド時間を縮めてくれるか、継続して見ていきたい。他のリポジトリでも同じ仕組みを使い回せるように作ってあるので、必要になったら増やしていく。

self-hosted runnerで無限CI - ねこの部屋