Github Actionsのコスト改善

AI駆動開発していると知らない間に無駄な処理も多くなっている。
Github の無料枠を超えてしまったので、処理の見直しを行うことに。
原因特定と対応方法を整理した。

●原因調査
以下のコマンドおよび、詳細のCSVを取得することで原因を調査することができる。
コマンドの「githubのユーザー名」、「リポジトリ名」「日付」は変更が必要。今回は2026/7/1以降で調査。

1)実行回数の確認

gh run list -R githubのユーザー名/リポジトリ名 -L 500 --json workflowName,createdAt \
  --jq '[.[] | select(.createdAt >= "2026-07-01")]
        | group_by(.workflowName)
        | map({n: .[0].workflowName, c: length})
        | sort_by(-.c)[] | "\(.c)\t\(.n)"'

2)実消費した時間(分)の確認 (この処理は数分かかります)

REPO=(githubのユーザー名)/(リポジトリ名)
SINCE=2026-07-01

gh api --paginate "/repos/$REPO/actions/runs?per_page=100&created=%3E%3D$SINCE" \
  --jq '.workflow_runs[] | [.id, .name] | @tsv' > /tmp/runs.tsv

while IFS=$'\t' read -r id name; do
  m=$(gh api "/repos/$REPO/actions/runs/$id/jobs?per_page=100" --jq '
    [.jobs[] | select(.started_at and .completed_at)
     | ((.completed_at|fromdateiso8601) - (.started_at|fromdateiso8601)) / 60 | ceil]
    | add // 0')
  printf "%s\t%s\n" "$m" "$name"
done < /tmp/runs.tsv |
awk -F'\t' '{s[$2]+=$1; c[$2]++} END {for (k in s) printf "%6d min  %4d runs  %s\n", s[k], c[k], k}' |
sort -rn

3)明細の取得
①GitHubにログイン → Settings → Billing and Licensing → Usage
 この画面で「Get usage report」を押下。
 ダイアログが表示されるので、「Detailed」を選択して「Email me the report」を押下。
 こちらも数分かかるが、メールが送付される。

●結果
上記3点の結果をAIに読み込ませて原因分析してもらう。

単発の事故 — 7月14日の突出(329分)は、Maestro E2E が1日で314分。月間14回の実行のうち大半がこの日に集中。E2E ワークフロー自体をデバッグして修正 push のたびに25分のジョブが最後まで走った結果。月の消費の12%を1日で失った計算。

恒常的な負荷 — それ以外の日は flutter_ci が毎日40〜90分を安定して消費。点線(1日64分)を常時超えているので、こちらが構造的な原因。

もう一点、functions_int_ci は他が0の日(7月10日、22日)でも5分だけ動いています。日次の cron が仕込まれていて、これだけで月155分。

●対策(ズボラ対応)
上記3点の結果をAIに読み込ませて対策を教えてもらう。具体的な指示は以下の通り。

GitHub Actions の消費分数を削減したい。実測データは以下。
【7月の実績】Linux 合計 2,590分(無料枠2,000分を7/24で使い切り)
flutter_ci 1,446分 / 163回 / 平均8.9分 ← 最大の恒常負荷
functions_int_ci 443分 / 91回 / 平均4.9分
maestro_e2e 351分 / 14回 / 平均25分(うち314分は7/14の1日に集中)
runbook_audit_ci 180分 / 191回 / 平均0.94分 ← ほぼ全て分単位切り上げの無駄
functions_ci 170分 / 58回 / 平均2.9分
【目標】月1,600分以下(1日52分以下)
【方針】品質ゲート(analyze / test / coverage)は PR で維持する。
実行タイミングと実行環境の最適化で削減し、チェック項目自体は減らさない。
まず .github/workflows/ 配下の5本を全て読み、以下の観点で
現状を報告してほしい。この段階ではファイルを変更しないこと。

  1. runbook_audit_ci.yml の中身を確認し、
    flutter_ci.yml のジョブ内の1ステップとして統合可能か判断する。
    191回×1分の切り上げ課金を消すのが目的。
  2. functions_int_ci.yml のトリガーを確認。
    日次 cron があれば週次(週1、平日深夜)に変更し、
    PR トリガーは main へのマージ時のみに変更する案を出す。
  3. flutter_ci.yml のジョブ構成を確認。
    checkout / FVM / flutter pub get を複数ジョブで重複実行しているなら、
    単一ジョブへの統合案と、それによる推定削減分数を出す。
  4. 全ワークフローの concurrency 設定の有無を確認。
    なければ group: ${{ github.workflow }}-${{ github.ref }} と
    cancel-in-progress: true を追加する。
  5. 全ジョブの timeout-minutes を確認。
    未設定なら flutter_ci/functions系は15分、maestro_e2e は30分を設定。
    デフォルト360分のまま放置しない。
  6. monorepo なので paths フィルタを確認。
    apps/project/flutter_app/ の変更で functions 系が起動していないか、
    apps/backend/ の変更で flutter_ci が起動していないか。
  7. maestro_e2e.yml のトリガーを確認。
    PR では run-e2e ラベル付き時のみ、加えて schedule と
    workflow_dispatch で動く構成にする案を出す。
  8. actions/upload-artifact の retention-days を確認。
    未設定なら 3 を設定(ストレージ枠 0.5GB も上限に達しているため)。
    【報告形式】
    ワークフロー名 / 現状の問題 / 修正案 / 推定削減分数 / CI が壊れるリスク
    報告後、リスクの低いものから順に修正プランを提示すること。
    1〜2(runbook統合、functions_int のトリガー変更)を最優先とする。

これで様子見。