マキモノ
開発プロセス無料✅ 公式検証済みv1.0.0 / 更新

GitHub Actions の課金分を実測して削る手順(cron 統合ダイエット)

GHA はジョブごとに分単位で切り上げ課金するため、数秒×高頻度の cron が最も割高になる。/timing API で全ワークフローの課金分を実測し、cron 式が完全一致するワークフローのステップへ統合して頻度も処理も変えずに削る手順。schedule は大量に間引かれるため分ゲートでの間引きが成立しないこと、統合すると前ステップの失敗で後続が silent skip されること、予算上限でジョブ未起動になった時の見分け方まで含む。

出品者: kim@orgiast.jp2 DL📖 読込 約3,942トークン (約6円)💰 コスパ 21
トークン節約メーター87%節約
ゼロからAIに作らせた場合9.5万トークン
このMDを読ませた場合1.2万トークン

8.3万トークンの節約 (API料金換算で約120円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。

この巻物について

GitHub Actions の課金分を実測して削る手順(cron 統合ダイエット)」は、開発プロセスカテゴリのAI指示書(MDファイル)です。GHA はジョブごとに分単位で切り上げ課金するため、数秒×高頻度の cron が最も割高になる。/timing API で全ワークフローの課金分を実測し、cron 式が完全一致するワークフローのステップへ統合して頻度も処理も変えずに削る手順。schedule は大量に間引かれるため分ゲートでの間引きが成立しないこと、統合すると前ステップの失敗で後続が silent skip されること、予算上限でジョブ未起動になった時の見分け方まで含む。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約8.3万トークン(API料金換算で約120円)・87%のトークンを節約できます。

カテゴリ
開発プロセス
対応AI
claude-code、cursor、codex-cli
ライセンス
商用利用可 (再販不可)
価格
無料
ゼロから開発時
約9.5万トークン
この巻物使用時
約1.2万トークン
節約量
約8.3万トークン (約120円)
更新日
2026-08-26

使い方 (AIに渡す3つの方法)

いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。

⬇ .md をダウンロード
claude "https://makimono-md.vercel.app/api/v1/files/github-actions-cron/raw を読み込んで、この指示書どおりに実装して"
claude-codecursorcodex-cliライセンス: 商用利用可 (再販不可)

中身

GitHub Actions の課金分を実測して削る手順(cron 統合ダイエット)

GitHub Actions の請求が思ったより高い、あるいは「Actions の予算上限に達してワークフローが全部止まった」ときに、 推測で頻度を落とさず、実測して安全に課金分だけを削るための手順書。

対象読者: private リポジトリで cron(schedule)を複数走らせているチーム。 このMDを AI エージェント(Claude Code / Codex 等)に読ませれば、そのまま調査から PR 作成・検証まで実行できる粒度で書いてある。


0. 前提となる課金モデル(ここを誤解していると必ず判断を間違える)

  • GitHub Actions は ジョブごとに実行時間を分単位で切り上げて課金する。
  • したがって 「数秒で終わる処理を高頻度で回す」のが最も損をする。 8 秒の処理を 15 分ごとに回すと、実計算 1.7 時間でも 月 766 分課金される。
  • 無料枠(private リポは月 2,000 分など、プランによる)を超えた分が請求される。
  • public リポは無料枠外でも動き続けるため、予算上限に達すると「private だけ止まる」紛らわしい状態になる。

予算上限に達したときの見分け方(コードを疑う前にここを見る)

gh run view <RUN_ID> の ANNOTATIONS に次が出る:

The job was not started because recent account payments have failed or your spending limit needs to be increased

ジョブが起動していないので --log-failed はログを返さない(BlobNotFound / 404)。失敗ステップも空になる。

# .jobs[].steps が空 = ジョブ未起動(課金・権限側の問題)。ステップ失敗とは原因が全く違う
gh api "repos/<OWNER>/<REPO>/actions/runs/<RUN_ID>/jobs" \
  --jq '.jobs[].steps[] | "\(.conclusion)\t\(.name)"'

復旧は支払い操作なので API では不可(user/settings/billing/* は 404、課金情報の読み取りにすら user スコープが必要)。 https://github.com/settings/billingBudgets and alerts で予算額を上げる。 Stop usage when budget limit is reached のチェックは外さない(硬い上限を残したまま枠だけ広げる)。 Receive budget threshold alerts(75/90/100%)は常に ON にしておく。


1. 実測する(見積りで判断しない)

実行時間は 一覧 API には入っていない/timing エンドポイントだけが返す。

REPO=<OWNER>/<REPO>
WF=<workflow-file>.yml

ids=$(gh api "repos/$REPO/actions/workflows/$WF/runs?event=schedule&per_page=100" \
        --jq '.workflow_runs[].id')
for id in $ids; do
  gh api "repos/$REPO/actions/runs/$id/timing" --jq '.run_duration_ms' 2>/dev/null &
done | awk '
  $1 > 10000 { n++; s += $1; m = int($1/60000); if ($1 % 60000 > 0) m++; billed += m }
  END { printf "runs=%d median_ish_s=%.0f avg_billed_min=%.2f\n", n, s/n/1000, billed/n }'
wait

注意点(実測で踏んだ罠)

  • billable.UBUNTU.total_ms0 を返すことがあるrun_duration_ms を使う。
  • $1 > 10000 のフィルタは必須。予算上限でジョブが起動しなかった run も 2〜4 秒の run_duration_ms を持つため、除外しないと平均が実態より軽く出て「削る必要なし」と誤判断する。
  • 全ワークフローについて 1回の課金分 × 月の実行回数 の表を作る。削る順番はこの表だけで決める。

2. 削り方を選ぶ(3 種類しかない)

実行時間頻度効く対策
数秒〜数十秒高頻度既存ワークフローのステップへ統合(起動オーバーヘッドを 1 回に集約)← 本命
数分以上低頻度実行時間そのものを縮める(依存キャッシュ・並列化・処理の絞り込み)
何でも何でも常時稼働マシン・夜間バッチ・関数サービスへ移す

短時間・高頻度なら統合が圧倒的に効く。新しく cron を作るときも、新規ワークフローを立てずに既存へステップとして足す。


3. 統合先の選び方 ← ここを間違えると「安くなったが処理が減った」になる

原則: cron 式が完全一致するワークフローへ寄せる

一致していれば実行頻度は変わらないので、挙動の変化はゼロ。

やってはいけない: 頻度が違うワークフローへ寄せて「分ゲート」で間引く

# ❌ 15分毎のジョブに hourly の処理を混ぜ、UTC 分 0-14 のときだけ叩く…という発想
MIN=$(date -u '+%-M')
if [ "$MIN" -ge 15 ]; then exit 0; fi

これは成立しない。GitHub は schedule大量に間引くため、cron 式と実発火は一致しない。実測例:

cron 式期待実際の発火
*/15 * * * *96 回/日41 回/日・間隔ランダム(最大 90 分空く)・分は事実上ランダム
0 * * * *24 回/日22〜23 回/日(ただし :00 には来ない。:13 :56 :49 等へ散る)

*/15 の実発火分の実測値: 30,04,07,55,23,59,28,55,23,12,55,21,01,47,16,52,14,41,59,43,...:00-:14 に入る run は全体の 約 23% しかなく、分ゲートでは hourly の処理が 23 回/日 → 約 10 回/日に落ちる。 集計系のエンドポイント(「直近 1 時間ぶんを集計して通知」等)だと、落ちた回のデータは二度と出力されず実質的なデータ欠損になる。

必ず実発火時刻を実測してから統合先を決める:

gh api "repos/$REPO/actions/workflows/$WF/runs?event=schedule&created=<YYYY-MM-DD>&per_page=100" \
  --jq '.workflow_runs[].created_at' | sort | awk -F'T' '{print $2}'

統合先の所要時間に「切り上げの余裕」があるか確認する

寄せ先が中央値 59〜79 秒(=2 分課金)なら、9 秒足しても 2 分のまま=増分ゼロ。 逆に中央値が 167 秒(=3 分課金、境界 180 秒に張り付き)なら、17 秒足すと 4 分課金へ転ぶ run が増える。 統合による増分も実測データで試算する(同じスクリプトで $1 + 17000 して billed を比べるだけ)。


4. 統合するときに必ず入れる if: ${{ !cancelled() }}

独立ワークフローだった頃は 1 本が落ちても他は動いた。 同一ジョブのステップに集約すると、前のステップが失敗した時点で後続が skipped になる。 これは統合で新たに作り込む障害なので、独立していた処理には必ず付ける。

jobs:
  poll:
    runs-on: ubuntu-latest
    steps:
      - name: Job A
        if: ${{ !cancelled() }}
        run: curl -sS -m 60 "$ENDPOINT_A" -w "HTTP %{http_code}\n"

      - name: Job B(独立した処理。A がコケても必ず走らせる)
        if: ${{ !cancelled() }}
        run: curl -sS -m 60 "$ENDPOINT_B" -w "HTTP %{http_code}\n"
  • continue-on-error: true使わない。失敗を成功扱いにして見えなくするため。 if: ${{ !cancelled() }} ならジョブ全体は赤いまま(失敗は見える)で後続だけ走る。
  • 逐次依存しているステップには付けないcheckoutinstallrun は失敗したら止まるのが正しい)。
  • curl-f を付けない限り HTTP 4xx/5xx では失敗しない。タイムアウト(exit 28)だけがステップを落とす。 つまり「重いエンドポイントがタイムアウトすると、その後ろの処理が全部止まる」構造になりやすい。

ステップの skip は run 一覧からは見えないので、統合前に既存ワークフローを点検しておく:

for id in $(gh api "repos/$REPO/actions/workflows/$WF/runs?event=schedule&per_page=60" --jq '.workflow_runs[].id'); do
  gh api "repos/$REPO/actions/runs/$id/jobs" \
    --jq '[.jobs[].steps[]? | select(.conclusion=="skipped" or .conclusion=="failure") | "\(.conclusion):\(.name)"] | join(" | ")' &
done | sort | uniq -c | sort -rn
wait

5. 統合を消さないための後始末

  • 統合した旧ワークフローファイルは 削除せず workflow_dispatch のみ残す(手動再実行の口を維持)。 ファイル先頭に「定期実行は <統合先>.yml のステップへ移した。schedule を付け直さないこと」と理由付きで書く。
  • 統合先のヘッダにも「なぜここに寄せたか(cron 式が一致するから)」「ここに違う頻度のものを混ぜてはいけない理由」を 実測値付きで残す。数字が無いコメントは次の担当者に無視される。

6. 検証(ここを省くと「安くしたつもり」で終わる)

  1. YAML をローカルでパースする(構文エラーだと GitHub 上ではワークフローが黙って動かなくなる)

    pip install --quiet pyyaml
    python -c "
    import yaml, glob, os
    for p in sorted(glob.glob('.github/workflows/*.yml')):
        d = yaml.safe_load(open(p, encoding='utf-8'))
        on = d.get('on', d.get(True))   # YAML 1.1 は on: を True に解釈する
        print(os.path.basename(p), list(on.keys()))
    "
    
  2. workflow_dispatch で 1 回叩いてステップの成否を見る(速いフィードバック)

  3. --event=schedule で実際に success することを確認する ← これが完了条件 手動実行が通っただけでは判定にしない。cron 経路だけで壊れることがある。

    gh api "repos/$REPO/actions/workflows/$WF/runs?event=schedule&per_page=3" \
      --jq '.workflow_runs[] | "\(.created_at) \(.status) \(.conclusion) \(.head_sha[0:7])"'
    
  4. 統合で失われた処理が無いことを機械照合する(統合前に各ワークフローが叩いていた エンドポイント/スクリプト名を列挙し、統合後のファイルに全て存在するか grep -c で数える)

  5. 統合先の所要時間が課金の切り上げ境界を越えていないことrun_duration_ms で確認する

  6. 削減額は次の請求サイクルで実測して報告する。見積りの時点で「削減した」と言わない


7. AI エージェントに実行させるときの注意

  • 作業は origin/main から切った worktree で行う(git worktree add -b <branch> <dir> origin/main)。 古い作業ブランチから PR を出すと、未マージの他人の作業を消す差分になる。 出した後 git diff --numstat origin/main HEAD削除行が自分の変更分だけかを必ず確認する。
  • cron の修正はデフォルトブランチにマージされて初めて効く。「PR が Merged」を完了判定にせず、 git show origin/main:<path> で実物を照合する。
  • YAML をインラインの python -c / node -e で書き換えない。シェル層でバックスラッシュが食われて run: | 内の行継続(\)やリテラル \n が壊れ、YAML が構文エラーになる。 ヒアドキュメント(cat > file <<'YAML')かファイル書き込みツールを使い、 書いた後に行継続の本数を数えて壊れていないことを確認する。
  • date -u '+%-M' のように先頭 0 を落とす書式を使う。08 / 09[ "$MIN" -ge 15 ] で 8 進数と解釈され integer expression expected になる。

実績(この手順で得られた結果)

private リポ 1 本、月 5,700 分・11 ワークフローの環境で:

  • 8 秒 × 766 回/月 のワークフローを、cron 式が完全一致する高頻度ワークフローのステップへ統合 → -766 分/月
  • 9 秒 × 449 回/月 のワークフローを、cron 式が完全一致する毎時ワークフローのステップへ統合 → -449 分/月 (所要 59〜79 秒の寄せ先なので +9 秒でも 2 分課金の枠内 = 増分ゼロ
  • 統合先の増分は実測 100 runs の試算で +195 分/月
  • 正味 約 1,020 分/月(約 $8/月)削減。実行頻度・処理内容の変更はゼロ
  • 副産物として、統合前から起きていた「前ステップの失敗で後続が silent skip」も同時に解消

よくある質問

「GitHub Actions の課金分を実測して削る手順(cron 統合ダイエット)」とは何ですか?

GHA はジョブごとに分単位で切り上げ課金するため、数秒×高頻度の cron が最も割高になる。/timing API で全ワークフローの課金分を実測し、cron 式が完全一致するワークフローのステップへ統合して頻度も処理も変えずに削る手順。schedule は大量に間引かれるため分ゲートでの間引きが成立しないこと、統合すると前ステップの失敗で後続が silent skip されること、予算上限でジョブ未起動になった時の見分け方まで含む。

どれくらいトークン(費用)を節約できますか?

ゼロから開発すると約9.5万トークンかかりますが、この巻物を使えば約1.2万トークンで済みます。差し引き約8.3万トークン(API料金換算で約120円)・87%の節約です。

どうやって使いますか?

無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。

どのAIツールに対応していますか?

claude-code、cursor、codex-cli に対応しています。

商用利用できますか?

ライセンスは「商用利用可 (再販不可)」です。

🤝 自分でAIを動かすのは、まだ不安…という方へ

この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。

AI代行堂を見る →

関連する巻物

開発プロセス無料✅ 公式

ドキュメント駆動開発プロセス CLAUDE.md — 作るものを固めてから書かせる

「AIが暴走して意図と違うものを作る」を根絶する開発プロセス指示書。UI仕様→機能設計→実装の順をAIに強制し、1ファイルごとに承認ゲートを挟む。受託開発・チーム開発向け。

86%節約
38.8万トークン (料金換算 約580円)
新着
開発プロセス無料✅ 公式

AIに指示書マーケットを自動参照させ、終了時に自動出品させるMD

開発依頼を受けた瞬間にマーケットの完成済み指示書を検索してAIに読ませ、セッション終了時には汎用ノウハウを自動出品させる仕組みの作り方。全台配布・秘密情報スキャン・実際に踏んだ配布バグ3つの回避込み。

88%節約
33.5万トークン (料金換算 約500円)
新着
開発プロセス無料✅ 公式

「そのPCにしか直せない障害」をAIに自分で気付かせて着手させる

特定の1台にしかリポジトリが無い機能は、修正手順を書いても誰にも実行されず放置される。SessionStart hook で当該PCのAIだけに指示を出し、完了後は指示書へ状態を書き戻して再実装事故を防ぐ型。走査の時間予算とセッション跨ぎの再開、メール一致だけの自動承認がなりすまされる理由と署名キー方式、状態問い合わせAPI、鍵の自動配布、no-op通知の抑止まで、実際に94件の滞留を解消した実例に基づく手順。

95%節約
22.8万トークン (料金換算 約340円)
新着

この巻物、誰かのトークンも救えます

𝕏 で節約レシートをシェア