ワダチを作る #2:ハコヅミの土台を写して、雛形・CI・デプロイを本番まで通した

前回(#1)で企画がまとまったので、今回は開発の土台を作りました。ハコヅミのときは雛形・CI・自動デプロイ・Accessまでを1本で書きましたが、今回はハコヅミのものを土台に写せるので、同じことが同じ日の午前中のうちに、本番のリリースまで終わりました。

やったことは次のとおりです。

  • ハコヅミの CLAUDE.md から、共通の方針だけを切り出す
  • スキル(/issue・/implement)と Issue テンプレートを移す
  • 雛形・CI・デプロイを作る
  • 最初のリリースで、本番(wadachi.jiru-labo.com)まで通す

作業は、ハコヅミと同じ「Issue → ブランチ → PR → マージ」で進めました。実装とPRはClaude Code、レビューと判断とマージは自分です。Issue は、GitHub Projects のボード(優先度と状態)にも入れて管理しています。


CLAUDE.md:方針だけを写して、実装ごとの決まりは写さなかった

ハコヅミの CLAUDE.md は、冒頭に「どのサービスにも通じる話」(共通方針)を置いて、2つ目のサービスのときに切り出す前提で書いてありました。ただ、中身は約600行あります。

多くは、実装した機能ごとの細かい決まりでした。フォームの二重送信の防止、招待の一覧、課金、ホーム画面に追加するときの注意、など。ワダチにはまだ実装がないので、そのまま写すと、存在しないコードの説明になります。

そこで、次の分け方にしました。

  • 写したもの:方針。前提、技術スタック、画面のスタイルの3段構え、環境(開発・本番)、開発の流れ、テストの振り分け、データ設計の共通ルール
  • 写さなかったもの:機能ごとの決まり。ワダチで同じものを作ったときに足す。ハコヅミから移す予定の土台(ログイン、管理者と凍結、登録数の上限など)は、「未着手の一覧」として名前だけ並べた
  • ワダチで変えたもの:デザイントークンの値は茶系、最初からマルチユーザー(ハコヅミは固定の値で始めて、あとで付け替えるマイグレーションが要った)、「その日」は利用者の時刻で決める、KV・R2・Stripeは必要になってから

方針の原本は Notion の「サービス開発の共通方針」ですが、最終更新が9月29日のままで、ハコヅミの CLAUDE.md のほうが新しい決定を含んでいました(結合テストはログインの流れだけにしたこと、E2Eは develop 向けのPRだけで流すこと、ボードの運用、など)。ワダチの CLAUDE.md は新しいハコヅミ側を基にして、Notion のほうも、あとから追記しました。


スキルとテンプレートも、ハコヅミ固有の話を外して移した

/issue と /implement のスキル、Issue のテンプレートは、ハコヅミのものを土台にしました。ここでも、写し方に迷いました。

ハコヅミのスキルには、「ギアは製品名で表す」「visibility の列」「E2Eの補助関数の名前」のような、ハコヅミのコードを前提にした話が入っています。これを全部外して、ワダチの CLAUDE.md とボードを指すようにしました。

一方、まだ雛形がない部分(テストの補助関数、コマンドなど)は、「雛形ができたら足す」とだけ書いて、具体的には書きませんでした。ないものを書くと、嘘になるためです。

ワダチで効く注意は、新しく足しました。たとえば、連続日数や達成率のテストには、日付の境界(日付が変わる前後、週の区切り、うるう年)を必ず入れる、です。


雛形:入れないものを決めた

雛形は、ハコヅミと同じバージョンの SvelteKit(Svelte 5)・TypeScript strict・Tailwind v4で作りました。トップページは「ワダチ」と一言だけです。

ここでは、入れないものを決めるほうが大事でした。

  • ログイン(better-auth)、決済(stripe)、fflate の依存は入れない(ハコヅミにある依存のうち、ワダチにまだ要らないもの)
  • Web フォント、CSP、UI部品は入れない(必要になったときに足す)
  • wrangler.jsonc は、開発用の分だけ。D1 以外のバインディング(KV、R2、送信回数の制限)は入れない

色は、トークンの名前をハコヅミと同じにして、値だけ茶系にしました。値は仮です。ハコヅミの「森」の配色と同じく、app.css の値だけで変えられます。

もう1つ、ハコヅミから写した scripts/check-colors.ts(パレットの色を直接書いたら lint で失敗する仕組み)が、そのままでは動きませんでした。調べる場所の src/lib/components が、まだないためです。「ない場所は何もしない」ように直しました。


CI:E2Eは分けない

CI は、ハコヅミの ci.yml を土台にしました。変えたところは次の2つです。

  • E2Eを分割しない:ハコヅミはE2Eを3つに分けて同時に流していますが、ワダチはテストがまだ1つなので、1つのジョブにしました。GitHub Actions の無料枠(月2,000分)は、ハコヅミと共有しています。ジョブを分けると、そのぶん、準備の時間も含めて分に切り上げて数えられるためです。遅くなったら、分けます
  • リリースの PR では E2E を流さない:ハコヅミと同じ。develop → main の PR では、型チェック・Lint・ユニットテストと、「main にだけ入った変更がないこと」の確認だけにする

この「main にだけ入った変更がないこと」の確認は、ハコヅミではシェルスクリプトだけで、テストがありませんでした。ワダチでは、使い捨ての Git リポジトリで本物の履歴を作って、スクリプトを流すテストを足しました。「main にだけ入った変更があれば失敗する」を、自動テストで確かめるためです。

最初のPRのCIは、check が44秒、e2e が52秒でした。


デプロイ:トークンは、サービスごと・環境ごとに作った

デプロイは develop → 開発用アカウント、main → 本番用アカウントです。ハコヅミと同じ作りで、GitHub の環境(development・production)ごとに、Cloudflare の API トークンとアカウント ID を入れます。

迷ったのは、API トークンをハコヅミのものと共有するかです。Cloudflare のトークンは、リポジトリではなくアカウントに対して発行されるので、使い回しても動きます。ただ、次の理由で別に作ることにしました。

  • トークンの値は、作ったときの1回しか見られない。ハコヅミのGitHubに入っているものは読み出せず、使い回すには値を作り直す必要があり、そうするとハコヅミのデプロイが止まる
  • 1つのトークンを2つのサービスで共有すると、漏れたとき、両方を同時に止めることになる
  • 名前(wadachi-development・wadachi-production)で、何用か分かる

本番用のトークンは、ゾーンの範囲を jiru-labo.com だけに絞りました。


Cloudflare Access:開発と本番で、付け方が変わった

開発環境は、ハコヅミと同じく、Cloudflare Access の後ろに置きます。ここで、途中でつまずきそうな点がありました。

開発環境:Workers の画面から付ける

開発環境は workers.dev の URL なので、Worker の「ドメイン」の画面から「Access を有効化」を押す形です。このとき、設定の画面の**スコープの初期値が「プレビューのみ」**になっています。そのままにすると、プレビューの URL だけが守られて、メインの wadachi.nori-suz.workers.dev は誰でも開けたままです。「すべての Traffic」に変えて、ポリシーは「Cloudflare account members」にしました。

設定のあと、curl で確かめました。200 ではなく 302(Access のログイン画面への移動)が返れば成功です。

本番:カスタムドメインなので、アプリケーションを自分で作る

本番は、workers.dev と Preview URL を閉じて、カスタムドメイン wadachi.jiru-labo.com だけを入口にしました(ハコヅミと同じ)。この場合、Workers の画面からは付けられないので、Zero Trust の「セルフホスト型」のアプリケーションを、自分で作ります。

ポリシーは、ハコヅミの「アカウントのメンバー」ではなく、自分のメールアドレス2つだけを許可する形にしました。誰が入れるのかが画面から分かるためです。今は自分しか使わないので、結果は同じです。

公開するときは、このアプリケーションを消します。


最初のリリース:本番まで通した

土台ができたところで、develop → main のPRを作って、最初のリリースをしました。マイグレーションがなく、main もまだ最初のコミットだけだったので、中身は単純です。

確かめたことは次のとおりです。

  • リリースのPRでは、e2e が飛ばされ、check だけが動いた
  • マージ後の本番のデプロイが、54秒で成功した
  • https://wadachi.jiru-labo.com で、トップページが開いた
  • 本番の workers.dev の URL と、バージョンごとの Preview URL は、404 になった(閉じている)

デプロイの前に心配していたのは、カスタムドメインを付けるときに、トークンの権限が足りるかでした。DNS の権限まで要るかもしれず、足りなければ本番のデプロイが落ちるためです。実際は、「Workers スクリプトの編集」「D1の編集」「ゾーンの Workers ルートの編集」のテンプレートのままで足りました。

もう1つ、確かめられた小さなことがあります。Markdown だけを変える PR では、CI もデプロイも動かない、という paths-ignore の設定です。実際に CLAUDE.md だけを変える PR を出して、チェックが1つも出ないことを確認しました。


おわりに

写して分かったのは、方針と、実装ごとの決まりは、分けて持つほうがよいということでした。方針は、どのサービスにも通用します。実装ごとの決まりは、そのコードがあって初めて意味があるので、写さず、同じものを作ったときに足すことにしました。

土台はこれで整いました。次は、最初の機能です。iPad mini でのタイマーの試作と、習慣の登録・記録の画面に進みます。

← トップページに戻る