refactor(control-plane): extract TenantInfraProvider interface (Epic A)#814
refactor(control-plane): extract TenantInfraProvider interface (Epic A)#8142witstudios wants to merge 1 commit intopu/epic-11-close-loopfrom
Conversation
Introduce a provider abstraction layer that decouples tenant lifecycle management from Docker Compose, enabling future infrastructure backends (AWS Fargate, Fly Machines) without changing the orchestration logic. New files: - providers/types.ts — TenantInfraProvider interface (7 methods) - providers/docker-compose-provider.ts — Docker Compose implementation - providers/__tests__/docker-compose-provider.test.ts — 16 provider tests Refactored: - provisioning-engine.ts — uses provider.provision/healthCheck/destroy instead of raw docker compose commands; extracts DB URL from in-memory env content instead of re-reading from disk - tenant-lifecycle.ts — uses provider.suspend/resume/upgrade/destroy instead of composing shell commands; deps reduced from 5 to 2 - index.ts — wires DockerComposeProvider via DI, supports INFRA_PROVIDER env var for future provider selection Schema: - Renamed dockerProject → infraId column - Added provider column (varchar, default 'docker') Zero behavior change — pure refactor. 212/212 tests pass, clean typecheck. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f8265149e0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| infraId: varchar('infra_id', { length: 255 }), | ||
| provider: varchar('provider', { length: 50 }).notNull().default('docker'), |
There was a problem hiding this comment.
Add a migration for the tenant infra columns
tenants now maps infra_id and provider, but the checked-in Drizzle artifacts still create/select the old shape: apps/control-plane/drizzle/0000_lovely_slayback.sql:37-54 defines docker_project only, and apps/control-plane/drizzle/meta/0000_snapshot.json:232-237 still snapshots that column. After pnpm --filter control-plane db:migrate, both fresh and upgraded databases will be missing infra_id/provider, so repository calls like select().from(tenants) will start failing with missing-column errors at runtime.
Useful? React with 👍 / 👎.
| await provider.provision(request.slug, envContent) | ||
| infraStarted = true |
There was a problem hiding this comment.
Trigger cleanup when provider.provision fails partway
The new infraStarted flag is only set after provider.provision() returns successfully. If the Docker provider has already written .env and docker compose up -d creates some resources before exiting non-zero, the catch block will skip provider.destroy() and leave partially created containers/volumes behind. Before this refactor, composeStarted was flipped before throwing on a failed compose-up specifically to run teardown in that scenario.
Useful? React with 👍 / 👎.
Summary
TenantInfraProviderinterface — a 7-method contract (provision,destroy,suspend,resume,upgrade,healthCheck,exec) that decouples tenant lifecycle management from any specific infrastructure backendDockerComposeProvider— moves all Docker-specific logic (compose commands, health polling, env file writing) into a single provider module, extracting it from provisioning-engine and tenant-lifecycleProvisioningDepsfrom 9 fields to 5, andLifecycleDepsfrom 5 fields to 2dockerProject→infraIdand addsprovidercolumn (default'docker') to support future multi-provider coexistenceINFRA_PROVIDERenv var in the entrypoint for future provider selection (currently onlydockeris supported)What changed
DockerComposeProvider(124 lines)provider.provision(),provider.healthCheck(),provider.destroy()docker_projectcolumninfra_id+providercolumnsFiles
New (4):
apps/control-plane/src/providers/types.ts—TenantInfraProviderinterfaceapps/control-plane/src/providers/docker-compose-provider.ts— Docker Compose implementationapps/control-plane/src/providers/index.ts— barrel exportsapps/control-plane/src/providers/__tests__/docker-compose-provider.test.ts— 16 testsModified (9):
services/provisioning-engine.ts— uses provider, removes fs/composePath/basePath/pollHealth depsservices/tenant-lifecycle.ts— uses provider, removes executor/composePath/basePath/pollHealth depsindex.ts— creates and wires DockerComposeProviderschema/tenants.ts—dockerProject→infraId, addedproviderVerification
pnpm --filter control-plane typecheckpassesWhy this matters
This is the foundation for the Firecracker migration path. Future providers (AWS Fargate, Fly Machines) implement the same
TenantInfraProviderinterface and get wired via theINFRA_PROVIDERenv var. The existing Docker path continues to work for local dev and VPS deployments.Test plan
🤖 Generated with Claude Code