デプロイ
GitHub Actions経由でアプリがRailwayのステージングと本番に出荷される仕組み。
デプロイは完全に自動化されています。コミットしてPRを開けば、プレビューURL付きでステージングに反映されます。mainにマージすれば本番に反映されます。ここでは裏で何が起きているかを説明し、うまくいかないときに何をすべきかが分かるようにします。
アーキテクチャ
- 1つのRailwayプロジェクト — プラットフォーム境界(認証、ネットワーク)。
- N個のRailwayサービス —
apps/*の各アプリに1つ。各サービスは独立してデプロイされる。 - Railpackがアプリをビルド(設定不要)。ルートの
pnpm-workspace.yamlを読み、対象アプリとその依存関係だけをビルド。
アプリごとの配線
各アプリには3つが必要です:
apps/<app-name>/deploy.config.yml— Railwayサービスを指し、環境変数マッピングを宣言。.github/workflows/deploy-app-<app-name>-staging.yml— 手動のworkflow_dispatchワークフロー(単発のステージングデプロイ用。PRで走るのはこれではありません — 次のセクション参照)。.github/workflows/deploy-app-<app-name>-production.yml—mainへのpushでパスフィルタ付きで起動。ほとんどのアプリはapps/<app-name>/**+shared/database/**でフィルタしますが、共有コードへの依存が広い一部のアプリ(vibe-coding-guide,staff-portalなど)は代わりにshared/**でフィルタします。どちらかはアプリのワークフローファイルで確認してください。
両方のアプリワークフローは共有の.github/workflows/deploy-reusable.ymlを呼び出し、そこで実際の処理を行います: pnpm install --frozen-lockfile → 必要ならtest → pnpm --filter <app> build → railway up。
デプロイの2つの経路
ステージング(PRを開いたとき)
単一のワークフローpr-preview-neon.ymlが、プレビュー全体を統括します:
- フィーチャーブランチにpushし、
mainへのPRを開く。 - スキーマが変わっていれば、マイグレーションを生成してPRにコミットバック。
- PRごとに1つのNeon DBブランチを作成(
preview/pr-<番号>-<ブランチ>)、14日で失効、マイグレーション適用済み。 pr-preview-neon.ymlが変更されたアプリを検出し、マトリックスジョブで各アプリについてdeploy-reusable.ymlを直接呼び出します — アプリごとのステージングワークフローはディスパッチされません。- 変更された各アプリはRailwayのステージング環境にデプロイされ、共有のNeon PRブランチに接続されます。
- 影響のある各アプリのプレビューURLがPRコメントに投稿されます。
Neon PRブランチはPRクローズ時に削除されます。
本番(マージしたとき)
- PRを
mainにマージ。 - 影響のある各アプリの本番ワークフローがパスフィルタ経由で起動。
- マイグレーションがNeon mainに適用される。
- Railwayが本番サービスを再デプロイ。
コードにシークレットが見えない理由
Railwayの環境変数は、再利用可能なワークフローがデプロイ時に注入します。ワークフローはapps/<your-app>/deploy.config.ymlのsecrets:ブロックを読み、GitHubのsecret/varsから値を取得してRailwayサービス環境にpushします。詳しいマッピングは環境変数を参照。
ログ
Railwayはstdoutとstderrのみをキャプチャします。console.log, console.warn, console.errorを使います。本番ではフィールドで検索できるようJSONでログを出します:
console.error(JSON.stringify({
level: 'error',
event: 'api_error',
error: error instanceof Error ? error.message : 'Unknown',
timestamp: new Date().toISOString(),
}));PII(メール、名前)やシークレットは絶対にログしないでください。ログをファイルやデータベースに書き込まないでください。
自動注入される変数
以下は宣言不要です — プラットフォームが設定します:
DATABASE_URL— 環境のデータベースサービスから注入。AUTH_UI_URL— 非認証サービスすべてに注入。
Claudeに聞く
デプロイが失敗したとき
- GitHub Actionsのワークフロー実行画面でどのステップが失敗したか確認。
- Lint/型チェック失敗 → ローカルで
pnpm build:<your-app>を実行して再現。 railway up失敗 → Railwayダッシュボードを開く、サービスログに原因が出ていることが多い。- 環境変数の欠損 → 環境変数を参照。
- マイグレーション失敗 → データベースマイグレーションエラーを参照。
クイズ
`apps/meal-planner/`配下のファイルだけを変更したPRを`main`にマージしました。どの本番サービスが再デプロイされますか?