#cloudflare-workers (3)
セットアップ手順の順序が重要
Slack の Event Subscriptions で Request URL を入力すると、即座に URL Verification チャレンジが送信される。Worker がデプロイ済み+Secrets設定済みでないと検証が失敗する。
正しい順序: Slack App 作成(URL は仮)→ Install → デプロイ&Secrets設定 → URL を本番に更新
Worker URL のサブドメインは予測できない
wrangler deploy の出力で初めて https://{worker-name}.{subdomain}.workers.dev が確定する。README にプレースホルダーを書くなら、デプロイ後に更新するフローを明記すること。サブドメインはアカウントごとに異なる。
PEM 秘密鍵は対話入力ではなくパイプで渡す
# NG: 対話入力だと改行が壊れる
wrangler secret put GITHUB_APP_PRIVATE_KEY
# OK: パイプ形式
cat /path/to/private-key.pem | wrangler secret put GITHUB_APP_PRIVATE_KEY
AI Gateway ID の確認方法
Cloudflare ダッシュボード → AI → AI Gateway で表示されるゲートウェイ名がそのまま ID。default という名前なら ID も default。Account ID は npx wrangler whoami で確認できる。
GitHub App Installation ID の確認方法
gh api /orgs/{org}/installations \
--jq '.installations[] | select(.app_slug=="your-app") | .id' 概要
社内ドキュメントサイト(VitePress + Cloudflare Pages)に対して、Slackから自然言語でドキュメント追加・修正を指示するとAIがMarkdownを生成しGitHub PRを自動作成するBotを構築した。
アーキテクチャ
Slack (/update-doc コマンド)
→ Cloudflare Workers(署名検証・ルーティング)
→ Claude API(AI Gateway経由、自然言語→Markdown変換)
→ GitHub REST API(ブランチ作成・ファイル追加・PR作成)
→ Slack(response_url にPRリンク返信)
実装プロセスの流れ
- マイルストーン定義 → タスク自動分解(15タスク、5マイルストーン)
- 基盤構築(MS20: 5タスク直列)→ Slack App登録・Workers雛形・署名検証・コマンドハンドラ・デプロイ
- 機能実装(MS21: 3タスク、一部並列)→ Claude API連携・GitHub API連携・フロー統合
- 各タスクをサブエージェントに委譲し、メインコンテキストを軽量に保つオーケストレーターパターン
技術的な知見
Slack Bolt は使わない
Workers環境ではNode.js依存が問題になるため、fetchハンドラに直接実装。Web APIベースで署名検証もHMAC-SHA256をWeb Crypto APIで自前実装。
3秒タイムアウト対策
Slackはコマンド応答を3秒以内に要求する。ctx.waitUntil()でバックグラウンド処理を起動し、即座に「処理中です…」を返す。完了後はresponse_urlにフォローアップ送信。
Workers のサブドメインは予測できない
wrangler deployの出力で初めてURLが確定する。READMEにプレースホルダーを書くと後で修正が必要になる。デプロイ後に確認して設定するフローにすべき。
Event Subscriptions の URL Verification
Slackの設定画面でRequest URLを入力すると即座にchallengeリクエストが飛ぶ。Workerがデプロイ済み+Secrets設定済みでないと検証が失敗する。設定手順の順序が重要。
GitHub App JWT認証(RS256)on Workers
PEM秘密鍵をcrypto.subtle.importKey("pkcs8", ...)でインポートし、crypto.subtle.sign("RSASSA-PKCS1-v1_5", ...)で署名。Installation Tokenはメモリキャッシュで有効期限管理。
設計判断
| 判断 | 理由 |
|---|---|
| Octokit不使用 | 依存を増やさない。fetchベースで軽量実装 |
| Zod不使用 | devDependencyに入っていないため型ガードで手動バリデーション |
| AI Gateway経由 | ログ・レート制限・モニタリングをCloudflareに委譲 |
| PRベース | レビューによる品質担保。誤った内容が直接公開されない |
+server.ts = サーバー専用APIエンドポイント
SvelteKitのファイル規約:
| ファイル | 役割 |
|---|---|
+page.svelte | ページUI(ブラウザ) |
+page.server.ts | ページ用サーバー処理 |
+server.ts | 純粋なAPIエンドポイント |
Next.jsとの対応:
| Next.js | SvelteKit |
|---|---|
app/api/xxx/route.ts | src/routes/api/xxx/+server.ts |
Cloudflare環境変数の取得パターン
// +server.ts 内(サーバー専用、フロントに露出しない)
const apiKey = platform?.env?.CLAUDE_API_KEY;
platform.env= Cloudflare Workers の Bindings(環境変数)process.envではなくplatform.envを使うのがCF固有のパターン?.は ローカル開発時にplatformが undefined になる可能性があるため