Cloudflare (ut-code のアカウント ut.code();) へのデプロイとプレビュー。デプロイは GitHub の CI ではなく、Cloudflare の Workers Builds (ダッシュボードで設定) が行う。
#3 で扱う。
| 状態 | |
|---|---|
本番の Web (kanban-web) |
デプロイ済み: https://kanban-web.ut-code.workers.dev |
メールを送る Worker (kanban-reminder-worker) |
デプロイ済み (cron は 15 分ごと)。公開 URL はない (workers_dev: false) |
| プレビュー | Worker Previews。ブランチごとに https://<ブランチ名>-kanban-web.ut-code.workers.dev |
| リソース | D1 2 個、R2 2 個、キュー 4 つ (下の表)。マイグレーションは本番とプレビューの両方に適用済み |
| シークレット | BETTER_AUTH_SECRET を、本番とプレビュー (全プレビュー共通) に設定済み (別の値) |
| Workers Builds | ダッシュボードで設定済み (下の 4 の値) |
| ビルドのトークン | kanban-deploy (kanban-web の本番とプレビュー)、kanban-reminder-deploy (kanban-reminder-worker)。ほかのプロジェクトのトークンは使わない |
| メール (Resend) | 未設定 (#8)。それまで、本番のメールの送信は失敗して、デッドレターキューに溜まる |
| GitHub ログイン | コードは対応済み。GitHub の OAuth App の作成と、本番へのキーの設定が未了 (#2)。キーを入れるまで、ボタンは出ない |
Cloudflare のリソースの名前は、Cloudflare のアカウントの中で一意になる (GitHub の org ではない)。共有のアカウントで他のプロジェクトとぶつからないよう、すべて kanban- で始める。
| 種類 | 本番 | プレビュー (全プレビューで共有) |
|---|---|---|
| Worker | kanban-web、kanban-reminder-worker |
(kanban-web の Worker Previews) |
| D1 | kanban-db |
kanban-db-preview |
| R2 | kanban-files |
kanban-files-preview |
| キュー | kanban-reminders、kanban-notifications、kanban-mail-dead-letter |
kanban-notifications-preview (取り出す側はない) |
名前を変えるときは、wrangler.jsonc (2 つ)、apps/web/wrangler.preview-migrations.jsonc、apps/reminder-worker/src/index.ts (通知のキューの名前)、package.json、justfile、e2e/start-server.sh、scripts/deploy-preview.sh と apps/web/src/lib/preview-name.ts (Worker の名前)、この docs をそろえて直す。
Wrangler が複数のアカウントにログインしているときは、どれを使うかを環境変数で指定する (指定しないと、対話できない場所ではエラーになる)。
export CLOUDFLARE_ACCOUNT_ID=df6c3acd32f66bd1eb95e50607684297 # ut.code();mainに入ると、Workers Builds が、本番の D1 にマイグレーションを適用してから、kanban-webをデプロイする。- merge しただけでは、マイグレーションは走らない。 Workers Builds のデプロイコマンドが
d1 migrations applyを実行して、初めて適用される。手元からはpnpm db:migrate:remote。 - マイグレーションはデプロイより先に走る。列の追加はそのままでよいが、列の削除や名前の変更は、古いコードが壊れるので、2 回に分けて出す。
kanban-reminder-workerは、別の Workers Builds のプロジェクトとしてデプロイする。
Worker Previews を使う。同じ Worker (kanban-web) のまま、ブランチごとに独立したプレビューができる。
- URL はブランチごとに固定:
https://<プレビュー名>-kanban-web.ut-code.workers.dev。プレビュー名は、ブランチ名を小文字、数字、-にしたもの (apps/web/src/lib/preview-name.ts。例:feat/worker-previews→feat-worker-previews)。同じブランチにプッシュすると、そのプレビューが更新される。複数のブランチを同時に見られる。 - Durable Objects は、プレビューごとに別の名前空間が自動で作られる。
- D1、R2、キューは、何も指定しないと本番と共有されてしまうので、
wrangler.jsoncのpreviewsブロックで、プレビュー用のものを指定している。D1 と R2 は全プレビューで 1 つを共有する (データも共有)。列の削除や名前の変更を含むブランチを出すと、他のブランチのプレビューが壊れることがある。壊れたら、プレビュー用の DB を作り直す。 - ログイン: ログインは
BETTER_AUTH_URLと同じオリジンからのリクエストしか受け付けない。プレビューごとに URL が違うので、scripts/deploy-preview.shが、wrangler preview --name <プレビュー名> --var BETTER_AUTH_URL:<そのプレビューの URL>で、プレビューごとに渡している。 - メール: キューを取り出す側 (コンシューマ) と cron は、プレビューでは動かない (Cloudflare の制約)。プレビューでは、メールは送られない。
- 1 つの Worker に、プレビューは 100 個まで (無料プラン)。超えると、古いものから自動で削除される。手で消すときは
wrangler preview delete --name <プレビュー名>。 - Worker Previews はオープンベータ (2026 年 9 月に公開)。
手元からプレビューを作る: pnpm deploy:preview (いまのブランチを、そのブランチ名のプレビューにする)。
参考: バージョン URL は使えない。 Cloudflare には、wrangler versions upload で作る「バージョン URL」(<ハッシュ>-kanban-web…) という別の仕組みもあるが、Durable Objects を持つ Worker では作られない (実際に試して、開けないことを確認した)。
| 名前 | どこに | 内容 |
|---|---|---|
BETTER_AUTH_SECRET |
web のシークレット (本番)、プレビューの base config のシークレット (全プレビュー共通) | 長いランダム文字列。本番とプレビューで別の値 |
BETTER_AUTH_URL |
web の vars (本番)。プレビューは scripts/deploy-preview.sh が渡す |
公開 URL。ログインのオリジン確認に使う |
RESEND_API_KEY |
reminder-worker のシークレット | Resend の API キー (ワーカー仕様) |
REMINDER_FROM |
reminder-worker の vars |
送信元アドレス。独自ドメインの検証が要る |
APP_URL |
reminder-worker の vars |
メールのリンクの先 (本番の公開 URL) |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET |
web のシークレット (本番だけ。プレビューには入れない) | GitHub でログインするとき (#2)。作り方は Web アプリ仕様 (アプリは 1 つで、本番とローカルの戻り先を登録する) |
cd apps/web
pnpm exec wrangler secret put BETTER_AUTH_SECRET # 本番
pnpm exec wrangler preview base-config secret put BETTER_AUTH_SECRET # 全プレビュー共通シークレットを入れた直後は、反映まで数十秒かかる。そのあいだ、ログインしているのに 401 になるなど、結果が一定しないことがある。少し待ってから試す。
kanban-web:
| 設定 | 値 |
|---|---|
| Root directory | / |
| Build command | pnpm install --frozen-lockfile && pnpm --filter @todo/web build |
Deploy command (main) |
pnpm --filter @todo/web exec wrangler d1 migrations apply kanban-db --remote && pnpm --filter @todo/web exec wrangler deploy |
| Production branch | main |
| Non-production branch builds | 有効 |
| Non-production deploy command | ./scripts/deploy-preview.sh |
| Build watch paths | apps/web/**、packages/**、scripts/**、pnpm-lock.yaml |
scripts/deploy-preview.sh は、ビルドの環境変数 WORKERS_CI_BRANCH からブランチ名を読む。Node で .ts を直接動かすので、Node 24 を使う (.node-version。Workers Builds も CI もこれに従う)。プレビュー用の D1 にマイグレーションを適用してから、wrangler preview でプレビューを作る。
kanban-reminder-worker (本番だけ):
| 設定 | 値 |
|---|---|
| Root directory | / |
| Build command | pnpm --filter @todo/reminder-worker typecheck (ビルドの手順はないので、型チェックだけ) |
| Deploy command | pnpm --filter @todo/reminder-worker exec wrangler deploy |
| Production branch | main |
| Previews | 無効 |
注意 (はまったところ):
- 本番のブランチは
mainにする。最初の設定で、本番のブランチが PR のブランチになっていて、PR のプッシュが本番のビルドとして扱われていた。 main以外のブランチは、「Previews」を有効にして、Preview command に./scripts/deploy-preview.shを入れる。Previews が無効だと、古い方式の「非本番のデプロイ」になり、PR のコメントにプレビューの URL が出ない。- ブランチの最初のビルドのときに、そのときの設定 (コマンド、トークン) が、そのブランチのプレビュー専用のトリガーに写される。あとから Worker の設定を変えても、既存のブランチには効かない。既存のブランチも直すときは、
cf builds triggers list --external-script-id <プレビューの ID>でトリガーを見つけて、cf builds triggers updateで直す (プレビューの ID はcf workers-builds workers previews list --script-tag <Worker のタグ>で分かる)。
ダッシュボードの表示と、実際に保存された値が違うことがあった。Cloudflare の CLI (cf) で、保存された値を直接読める。
npx -y cf auth login # 初回だけ。ブラウザで承認する
export CLOUDFLARE_ACCOUNT_ID=df6c3acd32f66bd1eb95e50607684297
npx -y cf workers scripts search # Worker のタグ (内部 ID) を調べる
npx -y cf builds workers get <タグ> # 本番のブランチ、コマンド、Previews の有無
npx -y cf builds triggers list --external-script-id <タグ>
npx -y cf builds logs get <ビルドの UUID> # ビルドのログcd apps/web
pnpm exec wrangler d1 create kanban-db
pnpm exec wrangler d1 create kanban-db-preview
pnpm exec wrangler r2 bucket create kanban-files
pnpm exec wrangler r2 bucket create kanban-files-preview
pnpm exec wrangler queues create kanban-reminders
pnpm exec wrangler queues create kanban-notifications
pnpm exec wrangler queues create kanban-mail-dead-letter
pnpm exec wrangler queues create kanban-notifications-previewできた database_id を、apps/web/wrangler.jsonc (本番と previews)、apps/web/wrangler.preview-migrations.jsonc、apps/reminder-worker/wrangler.jsonc に書く。そのあと pnpm db:migrate:remote、pnpm db:migrate:preview、シークレット (3)、pnpm deploy:web、pnpm deploy:worker。
-
mainへのマージで、本番にデプロイされ、マイグレーションが適用される - PR のブランチで、
<ブランチ名>-kanban-web.ut-code.workers.devにプレビューができ、ログインでき、本番のデータに触れない - リマインドの cron が動く (ダッシュボードの Triggers で、実行の履歴を見る)
- メールが届く (ワーカー仕様 の「未了」)
- デッドレターキュー (
kanban-mail-dead-letter) に、送れなかったメールが溜まっていない
pnpm check:deploy で、apps/web と apps/reminder-worker の設定が、まだ正しく読めることを確かめる (アップロードはしない)。CI の check ジョブでも実行する。