コンテンツにスキップ

Sora 2プロンプト管理のGitHub Actions自動化実装

この記事は実装ガイドのフォローアップです

元記事: Sora 2プロンプトのバージョン管理実装

ゴール

  • GitHub Actionsで Gist コミット時に Notion DB へ自動登録し、手動操作を完全排除
  • PR 作成時にプロンプト差分を自動コメント挿入し、レビュー時間を30%短縮
  • Secrets 管理とエラーリトライで本番運用耐性を確保

アーキテクチャ概要

[GitHub Gist Push]
      ↓ (webhook trigger)
[GitHub Actions Workflow]
      ├→ (1) Gist差分取得 (gh CLI)
      ├→ (2) Notion API登録 (Python script)
      └→ (3) PR差分コメント (GitHub API)

[Pull Request]
      ↓ (opened/synchronize)
[Workflow: PR Comment]
      ├→ プロンプト差分抽出
      └→ クレジット予測表を自動コメント

実装ステップ

ステップ1: Secrets設定とリポジトリ準備

GitHub リポジトリに以下のSecretsを登録します。

# GitHub Settings → Secrets → Actions で登録
NOTION_TOKEN=secret_xxx
NOTION_DATABASE_ID=abc123
GIST_TOKEN=ghp_xxx  # Gist読み取り権限付きPAT

リポジトリ構造例:

.github/
  workflows/
    sync-notion.yml
    pr-review.yml
scripts/
  sync_gist_to_notion.py
  extract_prompt_diff.py

ステップ2: Gist→Notion自動同期ワークフロー

Gistコミット時にNotion DBへ自動登録するワークフローを実装します。

name: Sync Gist to Notion

on:
  workflow_dispatch:
    inputs:
      gist_id:
        description: 'Gist ID to sync'
        required: true

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install requests tenacity

      - name: Sync to Notion
        env:
          NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
          DATABASE_ID: ${{ secrets.NOTION_DATABASE_ID }}
          GIST_TOKEN: ${{ secrets.GIST_TOKEN }}
          GIST_ID: ${{ github.event.inputs.gist_id }}
        run: python scripts/sync_gist_to_notion.py

Pythonスクリプト (scripts/sync_gist_to_notion.py):

import os
import json
import requests
from tenacity import retry, stop_after_attempt, wait_exponential

NOTION_TOKEN = os.environ["NOTION_TOKEN"]
DATABASE_ID = os.environ["DATABASE_ID"]
GIST_ID = os.environ["GIST_ID"]
GIST_TOKEN = os.environ["GIST_TOKEN"]

@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=2, max=10))
def add_to_notion(payload):
    url = "https://api.notion.com/v1/pages"
    headers = {
        "Authorization": f"Bearer {NOTION_TOKEN}",
        "Content-Type": "application/json",
        "Notion-Version": "2022-06-28"
    }
    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()
    return response.json()

def fetch_gist():
    url = f"https://api.github.com/gists/{GIST_ID}"
    headers = {"Authorization": f"token {GIST_TOKEN}"}
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json()

def main():
    gist = fetch_gist()
    for filename, file_data in gist["files"].items():
        if filename.endswith(".json"):
            prompt_data = json.loads(file_data["content"])
            payload = {
                "parent": {"database_id": DATABASE_ID},
                "properties": {
                    "Name": {"title": [{"text": {"content": prompt_data["id"]}}]},
                    "Prompt": {"rich_text": [{"text": {"content": prompt_data["prompt"][:2000]}}]},
                    "Credits": {"number": prompt_data["metadata"]["credits_used"]},
                    "Success": {"checkbox": prompt_data["metadata"]["success"]},
                    "Tags": {"multi_select": [{"name": t} for t in prompt_data["metadata"]["tags"]]}
                }
            }
            add_to_notion(payload)
            print(f"✅ Synced: {filename}")

if __name__ == "__main__":
    main()

ステップ3: PR差分コメント自動挿入

PR作成時にプロンプト差分を抽出し、クレジット予測と共にコメントします。

name: PR Prompt Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Extract prompt diff
        id: diff
        run: |
          git diff origin/main...HEAD -- '*.json' > diff.txt
          python scripts/extract_prompt_diff.py diff.txt > comment.md

      - name: Post PR comment
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('comment.md', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: body
            });

差分抽出スクリプト (scripts/extract_prompt_diff.py):

import sys
import json
import re

def parse_diff(diff_file):
    with open(diff_file) as f:
        content = f.read()

    changes = []
    for match in re.finditer(r'-"prompt": "(.*?)"\n\+"prompt": "(.*?)"', content, re.DOTALL):
        old, new = match.groups()
        changes.append({"old": old[:100], "new": new[:100]})

    if not changes:
        return "差分なし"

    table = "| 変更前 | 変更後 | 推定影響 |\n|--------|--------|----------|\n"
    for i, ch in enumerate(changes, 1):
        credit_impact = "+10" if len(ch["new"]) > len(ch["old"]) else "-5"
        table += f"| {ch['old'][:50]}... | {ch['new'][:50]}... | {credit_impact}cr |\n"

    return f"## プロンプト差分レビュー\n\n{table}\n\n推定合計影響: {sum([10 if len(c['new'])>len(c['old']) else -5 for c in changes])}cr"

if __name__ == "__main__":
    print(parse_diff(sys.argv[1]))

ベンチマーク:自動化前後の比較

指標手動運用Actions自動化改善率
Notion登録時間5分/件30秒/件90%短縮
レビュー準備時間15分/PR0分(自動)100%削減
同期ミス発生率12%0.5%96%減
月間工数削減-8時間-

実測条件: 3人チーム、月50件のプロンプト更新、2ヶ月間の運用データ

失敗パターンと回避策

症状原因回避策
Notion API 429エラー頻発レート制限超過tenacityでリトライ+バックオフ実装
Gist取得時の認証エラーPAT権限不足gist スコープ付きトークン再発行
PR差分が空でコメント失敗JSONファイル以外の変更検出git diff-- '*.json'フィルタ追加
Workflowが予期せず失敗Secretsの誤設定事前にworkflow_dispatchでテスト実行

自動化・拡張案

  • Slack通知統合: ワークフロー完了時にSlackへ差分サマリー通知
  • クレジット予測ML化: 過去データから機械学習モデルで精度向上
  • 定期バックアップ: 週次でNotion DBを JSON export して S3 保存
  • マルチリポジトリ対応: Organization全体のGistを一括監視
  • 承認フロー追加: 高コストプロンプトは手動承認後にNotion登録

次のステップ