--- name: pr-screenshot description: UI変更を含むPRで、agent-browserでスクリーンショットを撮影し、R2にアップロードしてPR本文に貼り付ける --- # PR Screenshot UI変更を含むPRのスクリーンショットを自動で撮影・アップロード・PR本文更新するスキル。 ## 使い方 ``` /pr-screenshot /pr-screenshot "ホバー状態も撮って" ``` 引数なしで実行すると、変更差分からUI変更対象ページを自動判断する。 ## 設定 R2の接続情報はローカル設定ファイル `.claude/skills/pr-screenshot/config.local.json` から読み取る(gitignore対象)。 ```json { "r2AccountId": "your-cloudflare-account-id", "r2Bucket": "your-bucket-name", "r2PublicUrl": "https://pub-xxx.r2.dev" } ``` **初回セットアップ**: このファイルが存在しない場合、スキル実行時にユーザーに値を聞いて作成する。 ``` SCREENSHOT_DIR=/tmp/pr-screenshots ``` ## ワークフロー ### Step 1: 変更差分の分析 現在のブランチとPR番号を特定する: ```bash git branch --show-current gh pr list --head "$(git branch --show-current)" --json number --jq '.[0].number' git diff --name-only develop...HEAD ``` 変更されたファイルパスから、影響を受けるUI画面を推定する: **推定ルール**: - `web/src/features/{feature}/` → その feature に対応するページ - `web/src/app/(main)/bills/` → 議案詳細ページ (`/bills/{id}`) - `web/src/app/(main)/page.tsx` → トップページ (`/`) - `web/src/app/(main)/kokkai/` → 国会会期ページ - `web/src/components/` → 影響範囲が広い。トップページ + 議案詳細を撮る - `admin/src/features/bills-edit/` → admin 議案編集ページ - `admin/src/features/bills/` → admin 議案一覧ページ - `web/src/app/globals.css` → トップページ + 議案詳細を撮る - `admin/src/app/` 配下 → 対応する admin ページ feature名からページを特定する対応表: - `bills` → `/bills/{id}` (議案詳細) - `interview-config` → `/bills/{id}/interview` (インタビューLP) - `interview-session` → `/bills/{id}/interview/chat` (チャット) - `interview-report` → `/report/{reportId}` (レポート) - `bill-difficulty` → `/bills/{id}` (議案詳細) **UIに関係しない変更のみの場合**(migration, test, server-only logic等)はスキップして終了。 ### Step 2: 環境セットアップ worktreeのパスを特定し(現在のディレクトリが worktree であることを前提)、devサーバーを起動する: ```bash # Supabase が起動中か確認 npx supabase status 2>&1 | head -5 # シードデータを投入(新カラム等を反映) pnpm seed # devサーバー起動(バックグラウンド) # web のみ: ポート3000 # admin も必要なら: ポート3001 npx dotenv -e .env -- pnpm --filter web run dev & # admin が必要な場合: # npx dotenv -e .env -- pnpm --filter admin run dev & # サーバー起動待ち sleep 8 ``` サーバーが起動したら、使用するポートを確認する(3000が使用中なら別ポートが割り当てられる): ```bash # 起動ログからポートを確認するか、curl で確認 curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 || curl -s -o /dev/null -w "%{http_code}" http://localhost:3002 ``` ### Step 3: スクリーンショット対象URLの構築 seed投入後、DBから議案IDを取得してURLを構築する: ```bash # 公開済み議案のIDを1件取得 npx supabase db query "SELECT id::text FROM bills WHERE publish_status = 'published' LIMIT 1;" ``` 取得したIDを使い、Step 1 で特定したページのURLリストを作る。 admin ページが対象の場合: ```bash # admin にログインが必要(session cookie取得) # admin は Basic Auth やメールログインが必要なので、URL直アクセスで取れない場合がある # → admin はログインフローを agent-browser で実行してからスクショを撮る ``` ### Step 4: スクリーンショット撮影 `agent-browser` でモバイルビューポート (390x844) でスクリーンショットを撮る。 ```bash mkdir -p /tmp/pr-screenshots # セッション名はPR番号を使う SESSION="pr-${PR_NUMBER}" # ビューポートをモバイルに設定 agent-browser --session $SESSION set viewport 390 844 # 各URLを開いてスクショ agent-browser --session $SESSION open "$URL" agent-browser --session $SESSION wait 3000 agent-browser --session $SESSION screenshot /tmp/pr-screenshots/screenshot-1.png ``` **注意点**: - ページ読み込み後 `wait 3000` で安定を待つ - 初回アクセスはコンパイルに時間がかかるので `open` がタイムアウトしたらリトライする - ツールチップやホバー状態が必要な場合は `hover` してから撮る - スクロールが必要な場合は `scroll down` してから撮る - 撮影後は `Read` ツールで画像を確認し、正しく表示されているか検証する **admin ページのログインフロー**: ```bash agent-browser --session $SESSION open "http://localhost:3001/login" agent-browser --session $SESSION snapshot -i # メールとパスワードを入力 agent-browser --session $SESSION fill "@eX" "admin@example.com" agent-browser --session $SESSION fill "@eY" "admin123456" agent-browser --session $SESSION click "@eZ" # ログインボタン agent-browser --session $SESSION wait 3000 # ログイン後、目的のページに遷移 ``` ### Step 5: R2 アップロード まず wrangler の認証状態を確認する: ```bash npx wrangler whoami 2>&1 ``` 「Not authenticated」等のエラーが出た場合、ユーザーに `! npx wrangler login` の実行を促す(ブラウザでのOAuth認証が必要なため、Claude側では実行できない)。認証が完了するまでこのステップを中断する。 `config.local.json` から設定を読み取ってアップロードする。 ```bash # config.local.json から値を取得(Bash の jq または Read ツールで読む) R2_ACCOUNT_ID=$(cat .claude/skills/pr-screenshot/config.local.json | jq -r '.r2AccountId') R2_BUCKET=$(cat .claude/skills/pr-screenshot/config.local.json | jq -r '.r2Bucket') R2_PUBLIC_URL=$(cat .claude/skills/pr-screenshot/config.local.json | jq -r '.r2PublicUrl') export CLOUDFLARE_ACCOUNT_ID=$R2_ACCOUNT_ID # PR番号ベースのパスでアップロード npx wrangler r2 object put "${R2_BUCKET}/pr-${PR_NUMBER}/screenshot-1.png" \ --file /tmp/pr-screenshots/screenshot-1.png --remote # 複数ファイルがある場合はそれぞれアップロード ``` 公開URLのパターン: ``` ${R2_PUBLIC_URL}/pr-${PR_NUMBER}/screenshot-1.png ``` ### Step 6: PR 本文にスクリーンショットを追加 `gh pr edit` でPR本文を更新する。既存の本文を取得し、スクリーンショットセクションを追加/更新する。 スクリーンショットが3枚以下の場合はテーブルで横並び(33%幅): ```markdown ## スクリーンショット | 説明1 | 説明2 | 説明3 | |:---:|:---:|:---:| | | | | ``` 4枚以上の場合は2列テーブル: ```markdown ## スクリーンショット | 説明1 | 説明2 | |:---:|:---:| | | | | | | ``` 既存のPR本文に `## スクリーンショット` セクションがある場合は置換する。ない場合は `## Test plan` の直前に挿入する。 ### Step 7: クリーンアップ ```bash # devサーバーを停止 pkill -f "next dev.*turbopack" 2>/dev/null # 一時ファイル削除 rm -rf /tmp/pr-screenshots ``` ## 注意事項 - `agent-browser` CLI がインストール済みであること - `npx wrangler` が認証済みであること(未認証の場合、ユーザーに `! npx wrangler login` を促す) - Supabase がローカルで起動中であること(`npx supabase start`) - seed データには固定IDがないため、DBクエリでIDを取得する - Next.js の `unstable_cache` により、seed直後でもキャッシュが効く場合がある。`.next` フォルダ削除 + サーバー再起動で解決する - admin ページは認証が必要。seed データの `admin@example.com / admin123456` でログインする