Split Worker Deploy Runbook (本番カットオーバー)

SSoT 参照: アーキテクチャ判断は ADR-0010 Split Cloudflare Workers、 rollback 手順は rollback-runbook.html、 通知 channel / severity は notification-strategy.html、 secret 一覧は api/scripts/secret-keys.txt を参照。 本 runbook は 「legacy monolith から 4 split worker への本番カットオーバー」と その後の継続運用手順のみ扱う。

1. 概要

ADR-0010 で決定した 3 worker 分割構成を本番に展開する手順。 従来は parky-api-prod 単一 Worker が api.parky.co.jp 全体を捌いていたが、 以下の理由で 3 worker に分割:

  • 影響半径の縮小: admin / marketing の壊れたコードが public ユーザーを巻き込まない
  • cron triggers 上限: Workers 無料プラン 5 slots を超える定期 job を分散
  • secret スコープの最小化: marketing 用 OAuth secret を public Worker に配らない

2026-05-11 update: 元々は store-sync 専用 Worker を加えた 4 worker 構成 (ADR-0010 旧版) だったが、 Phase 1 skeleton 状態のまま 2 週間 deploy されなかったため削除。store-sync queue consumer は admin Worker 内で従来通り稼働 (wrangler.admin.toml)。Phase 2 (2026-Q3 想定) で 再分離する際は git 履歴から復元。

1.1 3 Worker 構成

┌─────────────────────────────────────┐ │ api.parky.co.jp (Cloudflare Zone) │ └────────────────┬────────────────────┘ │ ┌───────────────────────────────┼─────────────────────────────────┐ │ │ │ ▼ /v1/admin/* ▼ /v1/marketing/* ▼ catch-all ┌─────────────────┐ ┌────────────────────┐ ┌───────────────────┐ │ parky-api- │ │ parky-api- │ │ parky-api- │ │ admin-prod │ │ marketing-prod │ │ public-prod │ │ │ │ │ │ (host catch-all) │ │ - admin routes │ │ - marketing routes │ │ - public/owner │ │ - cron HOURLY │ │ - newsletter cron │ │ - mobile bff │ │ - FCM_DISPATCH │ │ - x_posts cron │ │ - search/ai │ │ queue consum. │ │ - oauth callbacks │ │ │ │ - PLACES_REFRESH│ │ │ │ │ │ - X_AI_GENERATE │ │ │ │ │ │ - STORE_SYNC │ │ │ │ │ │ queue + DLQ │ │ │ │ │ └─────────────────┘ └────────────────────┘ └───────────────────┘ 共有 bindings (Hyperdrive / KV_CACHE / KV_IDEMPOTENCY / R2 / D1 INSTAGRAM_DB / RATE_LIMIT_USER/LOGIN/OTP / RateLimiterDO / ANALYTICS dataset) は api/wrangler.shared-bindings.toml を SSoT として 3 toml に手動同期する運用。

1.2 環境別の有効化状況 (2026-05-01)

env状態備考
dev 未デプロイ (本 runbook 適用予定) 4 split toml は配置済、deploy-api-dev.yml は legacy monolith のままなので Phase 2 で更新。
stg 未着手 stg 用 split toml セクションは Phase 3 で追加。
prod deploy workflow 配置済 / secret 未投入 本 runbook §3〜§5 で初回 cutover を実施。

2. legacy monolith deprecate のお知らせ

BREAKING 2026-05-01 npm run deploy:prod (= 旧 wrangler deploy --env prod) は 意図的に失敗する

本日 (2026-05-01) 以下を変更:

  • api/wrangler.toml[env.prod] セクション (旧 line 256-460) を コメントアウト
  • api/package.jsondeploy:prodecho "DEPRECATED" && exit 1 に変更
  • .github/workflows/deploy-api-prod.yml は workflow 名を "Deploy API (LEGACY DEPRECATED — split workers used instead)" に変更し、if: false で job を gate。push trigger も削除し workflow_dispatch のみ。

これらは 誤って monolith deploy が走ることを防ぐための多重防御。新規 deploy は本 runbook §3 以降で記載する 4 split worker workflow を使う。

3. prod 初回 deploy 手順

順序が重要: public → admin → marketing。 理由は §3.1 を参照。

3.1 deploy 順序の理由

#worker順序の根拠
1public host catch-all。これが最初に上がっていれば、admin / marketing の path-specific route が後から差し替わるまでの間、すべてのリクエストを public が一旦受ける (壊れたコードでなければ既存挙動と等価)。
2admin cron HOURLY (毎時) と FCM/PLACES/X_AI/store-sync queue consumer がここで稼働開始。public deploy 後 5 分以内に上げないと、その時間帯の cron が空振りになる可能性がある (host catch-all の public worker は admin cron handler を持たないため)。
3marketing OAuth callback を含むので最後。callback 受取中に worker 切替が起きると incomplete authorization が出る可能性がある。低トラフィック時間帯 (深夜 JST) を選ぶこと。

3.2 事前確認チェックリスト

  • api/wrangler.{public,admin,marketing}.toml[env.prod] セクションが定義済
  • 各 toml の prod bindings (KV / R2 / Hyperdrive / D1 / Queues / Rate Limiter) が wrangler.shared-bindings.toml [shared.prod.*] と一致 (scripts/check-wrangler-consistency.sh でチェック)
  • api/scripts/secret-keys-1p-map.json_TODO entry が必要分すべて埋まっている (Firebase / Apple / Google Play / OpenAI/Anthropic/Gemini など、本番で必須のもの)
  • 本番 Supabase project (ypqzhfyiteadvwipglzj) で baseline migration 適用済
  • Cloudflare Dashboard で api.parky.co.jp custom domain が public worker に attach 可能な状態 (CNAME / Workers Routes 設定確認)
  • dev で 4 worker split deploy が 1 回以上成功している (動作実証)

3.3 secrets 投入

新しい SECRETS_SOURCE=1password-map モードで 3 worker それぞれに投入:

cd parky/api

# 1. public
WRANGLER_CONFIG=wrangler.public.toml \
  SECRETS_SOURCE=1password-map \
  npm run secrets:prod:public

# 2. admin (store-sync 用 APPLE_* / GOOGLE_PLAY_* も admin Worker に投入)
WRANGLER_CONFIG=wrangler.admin.toml \
  SECRETS_SOURCE=1password-map \
  npm run secrets:prod:admin

# 3. marketing
WRANGLER_CONFIG=wrangler.marketing.toml \
  SECRETS_SOURCE=1password-map \
  npm run secrets:prod:marketing

SKIPPED として表示された key (_TODO 残置 entry) は、 以下のいずれかで対応:

  • 1P item を作成して map JSON を更新 (推奨)
  • file モードに一時切替して scripts/secrets.env 経由で投入
  • 未投入のまま deploy (graceful fallback が効く secret のみ。Firebase / Apple / Google Play は未投入だと該当機能が壊れるので NG)

3.4 deploy 実行 (manual workflow_dispatch)

各 workflow を順番に手動 trigger:

# 1. public (host catch-all)
gh workflow run deploy-api-public-prod.yml
gh run watch  # 完了確認

# 2. admin (cron HOURLY と queue consumer (store-sync / FCM / Places / X_AI) をここで開始)
gh workflow run deploy-api-admin-prod.yml
gh run watch

# 3. marketing (最後 — OAuth callback 完了確認)
gh workflow run deploy-api-marketing-prod.yml
gh run watch

各 deploy 完了で Sentry release event が parky-api-{worker}-prod project に作成される。

3.5 smoke test

# public health
curl -fsS https://api.parky.co.jp/healthz/ready

# admin worker (各 Worker は同一 /healthz を expose)
curl -fsS https://admin-api.parky.co.jp/healthz

# marketing worker (各 Worker は同一 /healthz を expose)
curl -fsS https://marketing-api.parky.co.jp/healthz

# store-sync queue は admin Worker が consume している。
# Cloudflare Dashboard > Queues > parky-store-sync-prod で depth が 0 で安定していることを確認。
wrangler queues list

3.6 観察ウィンドウ (24h)

  • 初回 cutover 後 24 時間は手動 deploy 禁止 (regression 観察)
  • Discord #p2-deploys に 3 worker 分の deploy 通知が出ていることを確認
  • Sentry の parky-api-{public,admin,marketing}-prod project で release tag (${GITHUB_SHA}) が登録されていること
  • SLO burn rate が baseline 以下を維持 (auto-rollback-prod.yml は vars.AUTO_ROLLBACK_PROD_ENABLED 未設定のため発火しない)

4. rollback 方法

4.1 個別 worker の rollback (推奨)

1 worker だけ問題が出た場合:

cd parky/api

# 該当 worker のみ前バージョンに戻す
npx wrangler@4.12.0 rollback --config wrangler.public.toml --env prod
# または
npx wrangler@4.12.0 rollback --config wrangler.admin.toml --env prod
# など

wrangler deployments list --config wrangler.public.toml --env prod で履歴を確認できる。 既存の rollback-runbook および deployment-rollback と整合した手順。

4.2 全 3 worker を同時 rollback

cutover 自体に問題が出た場合 (例: shared bindings の ID 衝突):

cd parky/api
for cfg in wrangler.public.toml wrangler.admin.toml wrangler.marketing.toml; do
  echo "rollback $cfg"
  npx wrangler@4.12.0 rollback --config "$cfg" --env prod || true
done

4.3 legacy monolith に完全復帰 (最終手段)

DESTRUCTIVE split worker 構成が完全崩壊した場合のみ。手順:

  1. api/wrangler.toml[env.prod] ブロック (現在コメントアウト中) の # プレフィックスを一括削除
  2. .github/workflows/deploy-api-prod.ymlif: falseif: true に変更
  3. api/package.jsondeploy:prod"wrangler deploy --env prod" に戻す
  4. 3 split worker を停止 (Cloudflare Dashboard で各 Worker を delete 可。route 競合があると monolith が api.parky.co.jp/v1/admin/* を受けられない)
  5. npm run deploy:prod
  6. 事後に postmortem 作成 (postmortem-template)

5. 必要 secret / 設定

secret用途取得元
OP_SERVICE_ACCOUNT_TOKEN 1Password から CF API token / Sentry token / Discord webhook を引く repo secrets (既存)
CLOUDFLARE_API_TOKEN 1P fallback. wrangler の認証 1P op://p3ezteh54f3msvl4wqyw7gbiam/fckmphwmq7pccoyg6ye3vf4f34/credential
SENTRY_AUTH_TOKEN release tracking + sourcemap upload 1P PLACEHOLDER (item ID 未確定)、または repo secrets fallback
DISCORD_WEBHOOK_DEPLOYS Worker deploy 完了通知 (#p2-deploys) 1P op://p3ezteh54f3msvl4wqyw7gbiam/z6mu3s6cwa6ymyweilvdkk6czm/credential
3 worker 個別の app secret Supabase / Firebase / Resend / OAuth client / Discord webhook 5 本 / PostHog / Stripe 等 api/scripts/secret-keys-1p-map.json 参照 (SECRETS_SOURCE=1password-map モードで一括投入)

6. ファイル一覧

  • api/wrangler.public.toml — public Worker 設定 (host catch-all)
  • api/wrangler.admin.toml — admin Worker 設定 (/v1/admin/* + cron HOURLY + FCM/PLACES/X_AI/STORE_SYNC queue consumer + DLQ)
  • api/wrangler.marketing.toml — marketing Worker 設定 (/v1/marketing/* + newsletter/x_posts cron + OAuth callback)
  • api/wrangler.shared-bindings.toml — shared bindings SSoT (3 toml で手動同期)
  • api/wrangler.toml — legacy monolith。[env.dev]/[env.stg] は稼働中、[env.prod] は 2026-05-01 にコメントアウト済
  • api/scripts/set-secrets.shWRANGLER_CONFIG + SECRETS_SOURCE=1password-map 対応
  • api/scripts/secret-keys-1p-map.json — secret key → 1P op-ref マッピング (dev/prod 個別)
  • .github/workflows/deploy-api-public-prod.yml — public Worker prod deploy (workflow_dispatch)
  • .github/workflows/deploy-api-admin-prod.yml — admin Worker prod deploy (workflow_dispatch)
  • .github/workflows/deploy-api-marketing-prod.yml — marketing Worker prod deploy (workflow_dispatch)
  • .github/workflows/deploy-api-prod.yml — legacy monolith。if: false で gate 済 (Phase 2 で完全削除)
  • (deleted 2026-05-11) api/wrangler.store-sync.toml / .github/workflows/deploy-api-store-sync-prod.yml — Phase 1 skeleton を削除、queue consumer は admin Worker 内で継続。Phase 2 で再分離する場合は git 履歴から復元

7. 関連 docs

8. follow-up (Phase 2 / Phase 3)

  • Phase 2: deploy-api-{public,admin,marketing}-prod.ymlon: push: branches: [main] trigger を追加 (3 回手動成功してから)
  • Phase 2: deploy-api-dev.yml / deploy-api-stg.yml も split 化 (現状は legacy monolith 用の単一 workflow)
  • Phase 2: legacy deploy-api-prod.ymlwrangler.toml [env.prod] 完全削除 (split worker が 30 日以上安定運用後)
  • Phase 2 (2026-Q3 想定): store-sync Worker 再分離 (git 履歴から wrangler.store-sync.toml / src/store-sync-worker/ / GHA workflow を復元 → admin Worker から queue consumer を剥がす)
  • Phase 3: 3 worker 個別の canary deploy workflow (canary-deploy-{public,admin,marketing}-prod.yml) を整備
  • Phase 3: auto-rollback-prod.yml を 3 worker SLO 個別監視に拡張