GitHub Actions の無料枠2,000分を使い切った原因は、10月4日から失敗し続けていたCIだった
GitHub Actions の無料枠2,000分を使い切った原因は、10月4日から失敗し続けていたCIだった
GitHub から通知が来た。 今月の Actions 無料枠2,000分を、100%使い切ったという。 次のリセットは11月1日だ。
その直後から、Eurekapu の自動テストが3〜4秒で失敗する実行が出はじめた。 利用枠が原因かもしれない。 ただ、エラーの詳細も追加課金の設定も、まだ確認できていなかった。 再実行する前に、Actions のエラー表示と利用上限を確かめたほうがよさそうだと考えた。
同じセッションでは、直前まで「サブエージェントのプロンプトキャッシュは5分しか持たない(本体は1時間)」という話の真偽を、手元のログで確かめていた。 TTL が違うのは本当で、「5分を過ぎるとフルプライスがドカンと来る」は言い過ぎだった。 こちらは Claude Code のサブエージェントのキャッシュ寿命を測った記事 にまとめてある。 その記事をまとめるよう頼むのと一緒に、Actions の件も Claude Code に調べさせた。
3〜4秒で落ちる理由と、枠を減らした理由
3〜4秒で落ちる原因は、支出上限だと確定した。
ただし、それは枠を使い切ったあとの話である。 10月の枠を使い切った本当の原因は、CI が10月4日から失敗し続けていたことだった。
自分の見立ては、こうだった。 失敗が30個あり、そのうち長時間かかって失敗したのが28回ある。 ほぼこの28回が原因だろう。 毎回エラーが出ていて困っていたので、そのまま修正を頼んだ。
調べさせると、失敗の原因は1つではなかった。 主因はカード枚数のテストで、ほかにも2種類の失敗が混ざっていた。
時間の使い方にも偏りがあった。
ユニットテストの所要時間の89%(23.5分)を、excelSceneBookRegression.test.ts の1本が占めていた。
gh に user スコープを足す
並行して、自分のターミナルから次のコマンドを打った。
gh auth refresh -h github.com -s user
コマンドは120秒のタイムアウトで打ち切られ、バックグラウンドに回された。 コードを入力すると、アクセスできた。 認証が通ってから、支出上限の確認と、直したテストの手元での実行を Claude Code に同時に進めさせた。
3つの原因の修正と push
CI が毎回落ちていた原因を3つとも直させ、コミットして push した(6e93d9e5)。
このとき、別のセッションが sim-modules のファイルをステージしていた。
それは巻き込まず、パスを指定して自分の4ファイルだけをコミットさせた。
ただし、GitHub 上の CI で通るかはまだ確かめられていない。 Actions は枠切れで、11月1日まで動かないからだ。
回帰テストを Actions で回すか
回帰テストは、ローカルで流してもタイムアウトしていた。 それなら GitHub Actions で回さないほうがいいのではないか、と自分から言った。
返ってきたのは、その対応はもう済んでいる、という答えだった。
6e93d9e5 で、CI のユニットテストに SCENE_TARGETS=none が付いていた。
GitHub Actions では、画面再現の回帰テスト2本(excelSceneRegression と excelSceneBookRegression)はもう流れない。
この2本が飛ばされることも、Claude Code が手元で SCENE_TARGETS=none を付けて確かめてあった。
手元で全区間を一度に流すとタイムアウトするのは、excelSceneBookRegression だけで23分かかるためだ。
台本やエンジンを直したときは、変更が効く区間だけを手元で流す。
# CI 側:画面再現の回帰テスト2本を飛ばす
SCENE_TARGETS=none
# 手元:変更が効く区間だけを流す
node scripts/test-scene-regression.mjs --changed
自分が言い出したときには、同じ線引きがもうコミットに入っていた。
別セッションの差分がターミナルに混じる
コミットの話の途中で、ターミナルに別セッションの差分が混じって表示されていた。 表示だけでなく、セッションログにも混じっているのではないか。 もしそれがコンテキストに入っているなら、完全にバグである。 そう考えて、このセッションのログファイルを見に行かせた。
ログには記録されていた。 ただし、AI に渡るコンテキストには入っていなかった。
最初は「ログには記録がなく、ターミナルの表示だけの問題」と受け取り、不思議だと聞き返した。 答えは逆で、ログには記録されているので、ターミナルの表示だけの問題ではない、とのことだった。 コンテキストに入っていないことは、確認済みだという。
積み残しの片付けとメモリの逼迫
積み残しを尋ねると、3件残っていた。 1件目は、キャッシュの記事がまだ未コミットで、公開されていないことだった。
記事をコミットさせ(4628b1e5)、続けて11月1日のタスクの登録へ進めさせた。
そのあと、デプロイ前の検査に入った。
未公開の別記事を一時的に退避し、未公開記事へのリンクを文字表記に直して、検査を流し直した。
検査はすべて通り、デプロイは11時39分に始まった。
見込みは12〜20分で、プリレンダー(3,117ページ)まで進んだ。
ここで、手元のメモリがパンパンになった。 一旦止めてほしいと頼んだ。
デプロイはプリレンダーの途中で止まり、本番にはまだ何もアップロードされていなかった。 退避していた記事も元に戻した。
メモリの使い道を調べさせると、一番大きいのは eurekapu-nuxt4 の開発サーバー(ポート3200)だった。
| 使っているもの | メモリ |
|---|---|
開発サーバーの下にぶら下がる workerd 143個 | 約6GB |
| 開発サーバー本体 | 1.9GB |
| 合計 | 約8GB |
振り返り
- テストが3〜4秒で落ちる失敗と、枠を減らした失敗は別物だった。前者の原因は支出上限で、後者は10月4日から失敗し続けていた CI だった
- ローカルでもタイムアウトする回帰テストは、CI から外した。CI では
SCENE_TARGETS=noneで飛ばし、手元では--changedで変更が効く区間だけを流す
直した 6e93d9e5 が GitHub 上で通るかどうかは、11月1日に枠が戻るまで分からない。