GitHub Actions の CI コスト最適化: ブログ記事 PR 向け paths filter 設計
自動化が進んでブログ記事の生成頻度が増加すると、GitHub Actions の CI 実行時間とコストが急激に膨らむ課題が発生します。特に記事専用の PR では、通常のコード変更で必要な全 CI を実行する必要がないため、適切な条件分岐で大幅なコスト削減が可能です。
この記事では、ブログ記事 PR に対する CI の最適化設計と、paths filter を活用した workflow の効率的な制御方法を実践例とともに解説します。
CI コスト問題の背景
自動生成ブログのコスト試算
analytics-note では、Issue からのブログ記事自動生成を org 全リポジトリに拡張したため、1日10〜20件のペースで記事が生成される見込みとなりました。
1記事あたりの実測 CI 実行時間:
| workflow 種別 | 実行時間 | 用途 |
|---|---|---|
| 記事生成本体 | 3〜4分 | Claude による記事生成 |
| queue 検出・PR作成 | 30秒 | 自動化パイプライン |
| ビルド検証・自動マージ | 1〜1.5分 | 品質担保 |
| PR付随CI | 3〜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 レベルでの条件分岐を組み合わせます:
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 実行時間の定期的なレビュー
関連記事
- GitHub Project と Workflows の連携による開発自動化 — GitHub Actions の基本的な自動化パターン
- AI ブログ記事生成の品質ゲート設計と CI 検証 — ブログ記事の品質担保における CI の役割
出典 Issue
- perf(ci): blog PR 向けに Actions 分数を絞る(paths filter / skip 条件) — source repo:
analytics-note/analytics_note