GitHub Actions の CI 費用を paths filter で減らす

自動生成したブログ記事の PR が増えると、GitHub Actions の実行時間と料金が膨らみます。paths filter と条件分岐で不要な workflow を動かさない設計と、削減効果の測り方、実装の注意点を解説します。

6分で読めます Tech
大量のブログ PR が paths filter のじょうごで絞り込まれ、Actions 分数チャートが下降する、CI コスト最適化の概念図
この記事は AI が下書きを補助し、運営者が内容を確認して公開しています。

GitHub Actions の CI コスト最適化: ブログ記事 PR 向け paths filter 設計

ブログ記事を自動生成していて、GitHub Actions(GitHub 上で処理を自動で動かす仕組み)の利用料が気になっている方向けの記事です。自動化が進んでブログ記事の生成頻度が増えると、CI(変更のたびにビルドやテストを自動で走らせる仕組み)の実行時間とコストが急に膨らみます。

特に記事だけを追加する PR(プルリクエスト:変更内容を取り込む前に確認するための依頼)では、コード変更向けの CI をすべて動かす必要はありません。そのため、条件をうまく分ければコストを大きく減らせます。

この記事では、ブログ記事 PR 向けに CI を絞り込む設計と、paths filter(変更されたファイルの場所によって処理を動かすかどうかを決める設定)を使った workflow(GitHub Actions で自動実行する処理のまとまり)の制御方法を、実例とともに解説します。

CI コスト問題の背景

自動生成ブログのコスト試算

analytics-note では、Issue(GitHub 上の課題管理チケット)からブログ記事を自動生成する仕組みを、org(GitHub の組織アカウント)配下の全リポジトリに広げました。その結果、1日10〜20件のペースで記事が生成される見込みとなりました。

1記事あたりの実測 CI 実行時間:

workflow 種別実行時間用途
記事生成本体3〜4分Claude による記事生成
queue 検出・PR 作成30秒自動化パイプライン
ビルド検証・自動マージ1〜1.5分品質担保
PR 付随 CI3〜5分最適化対象
合計約8〜10分

月間コスト試算(GitHub Pro 3000分枠との比較):

  • 10件/日 × 30日 = 約3000分(枠ギリギリ)
  • 15件/日 × 30日 = 約4500分($12/月の超過)
  • 20件/日 × 30日 = 約6000分($24/月の超過)

削減余地の特定

ブログ記事 PR は apps/site/src/content/blog/*.mdx ファイルの追加のみが想定されるため、以下の CI は不要です:

  • コード品質チェック(lint:書き方の誤りを自動で検出するツール/test:動作確認の自動テスト)
  • インフラ関連の検証
  • 依存関係チェック
  • セキュリティスキャン(一部を除く)

ただし、記事内容の機密情報漏洩チェックは維持する必要があります。

paths filter による workflow 最適化

基本的な paths filter パターン

GitHub Actions では、paths と paths-ignore で workflow の実行条件を制御できます:

# ブログ記事のみの変更では実行しない
on:
  pull_request:
    paths-ignore:
      - 'apps/site/src/content/blog/**'
      - '!apps/site/src/content/config.ts'  # schema変更時は除外

条件分岐による細粒度制御

より柔軟に制御したい場合は、job(workflow の中で実行される個々の処理単位)ごとの条件分岐を組み合わせます。

jobs:
  check_changes:
    runs-on: ubuntu-latest
    outputs:
      blog_only: ${{ steps.changes.outputs.blog_only }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v2
        id: changes
        with:
          filters: |
            blog_only:
              - 'apps/site/src/content/blog/**'
            config:
              - 'apps/site/src/content/config.ts'

  lint:
    needs: check_changes
    if: needs.check_changes.outputs.blog_only != 'true'
    runs-on: ubuntu-latest
    # ... lint処理

セキュリティチェックの選択的実行

記事内容のセキュリティチェックは、対象ファイルを絞って継続実行します:

secret_scan:
  needs: check_changes
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - name: Scan secrets in blog content only
      if: needs.check_changes.outputs.blog_only == 'true'
      run: |
        # MDXファイルのみをスキャン
        secret-scan apps/site/src/content/blog/
    - name: Full secret scan
      if: needs.check_changes.outputs.blog_only != 'true'
      run: |
        # 全ファイルをスキャン
        secret-scan .

実装時の注意点

1. 既存 PR への影響回避

paths filter の追加は既存の通常 PR に影響しないよう設計する必要があります:

  • ブログ以外の変更では従来通り全 CI を実行
  • 混在 PR(ブログ + コード変更)では安全側に倒して全 CI を実行
  • テスト環境での十分な検証

2. 例外ケースの考慮

以下のケースでは通常の CI を実行する必要があります:

  • frontmatter(記事冒頭に書くタイトルや日付などの情報)の schema(項目の形式を決めた定義)の変更(config.ts の修正)
  • ビルドに影響するコンテンツ構造変更
  • 新しい記事カテゴリの追加

3. モニタリングの継続

最適化後も CI の実行状況を継続的に監視します:

# 最近のworkflow実行時間を確認
gh run list --limit 20 --json conclusion,createdAt,durationMs

# ブログPRの平均実行時間を算出
gh pr list --label "feat(blog)" --state merged \
  --json number,title,mergedAt --jq '.[].number' | \
  xargs -I {} gh pr view {} --json statusCheckRollup

削減効果の測定

Before/After 比較

最適化前後での実行時間比較:

項目最適化前最適化後削減率
ブログ PR 実行時間8〜10分4〜6分40〜50%
月間 Actions 分数4500分2700分40%
超過コスト$12/月$0/月100%

継続的な改善

CI 最適化は一度で終わりではなく、workflow の追加や変更に合わせて継続的に見直す必要があります:

  • 新しい workflow 追加時の paths filter 設定チェック
  • ブログ記事の構造変更時の条件見直し
  • Actions 実行時間の定期的なレビュー

まとめ

  • 記事だけを追加する PR では、コード変更向けの lint やテストを動かす必要がありません。paths と paths-ignore で実行条件を絞ると、CI の実行時間と料金を減らせます。
  • 絞り込むときも、記事の内容に機密情報が混ざっていないかの検査は、対象ファイルを絞って残します。
  • ブログとコードの変更が混ざった PR は安全側に倒して全部の CI を動かし、frontmatter の schema を変えたときも通常の CI を通します。

関連記事

この記事のもとになった記録

この記事は、筆者の作業記録「perf(ci): blog PR 向けに Actions 分数を絞る(paths filter / skip 条件)」をもとに書いています。この記録は非公開のため、リンクは付けていません。

更新履歴

  • 2026-11-02: 定期点検で、本文の12か所を直しました。