diff --git a/docs/preview.md b/docs/preview.md index a22dfa4..91967d6 100644 --- a/docs/preview.md +++ b/docs/preview.md @@ -14,6 +14,152 @@ Two modes: **Key design decision: No database table.** Docker IS the source of truth. Instead of persisting rows, we query Docker directly via compose project names, container labels, and `docker compose` CLI commands. +## Setting Up Preview Deployments for a Project + +### Prerequisites + +- **Docker** installed and running (`docker --version` / `docker compose version`) +- **Project registered** in Codewalkers (`cw project add` or via the UI) +- **Browser**: Chrome or Firefox recommended. Safari requires manual `/etc/hosts` entries for `*.localhost` subdomains. + +### Quick Start + +1. **Add a `.cw-preview.yml`** to your project root. This tells Codewalkers how to build and run your app: + +```yaml +version: 1 +services: + app: + build: . + port: 3000 +``` + +That's it for a single-service app with a Dockerfile. Run: + +```sh +cw preview start --initiative --project --branch +``` + +Open the URL printed in the output (e.g. `http://abc123.localhost:9100`). + +### Don't Have a `.cw-preview.yml`? + +The config reader auto-discovers in this order: + +1. **`.cw-preview.yml`** — full control (recommended) +2. **`docker-compose.yml` / `compose.yml`** — uses your existing compose file +3. **`Dockerfile`** — builds a single `app` service on port 3000 + +If your project already has a Dockerfile or compose file, previews work out of the box with zero config. + +### Multi-Service Example + +A typical full-stack app with frontend, backend, and database: + +```yaml +version: 1 +services: + frontend: + build: + context: . + dockerfile: apps/web/Dockerfile + port: 3000 + route: / # serves the root path + healthcheck: + path: / + interval: 5s + retries: 10 + env: + VITE_API_URL: /api + dev: # optional: used in dev mode + image: node:20-alpine + command: npm run dev -- --host 0.0.0.0 + workdir: /app + + backend: + build: + context: . + dockerfile: packages/api/Dockerfile + port: 8080 + route: /api # proxied under /api/* + healthcheck: + path: /health + env: + DATABASE_URL: postgres://db:5432/app + + db: + image: postgres:16-alpine + port: 5432 + internal: true # not exposed through the proxy + env: + POSTGRES_PASSWORD: preview +``` + +Requests to `http://.localhost:9100/` hit `frontend:3000`, requests to `/api/*` hit `backend:8080`, and `db` is only reachable by other services. + +### Config Reference + +Each service in `.cw-preview.yml` supports: + +| Field | Required | Description | +|-------|----------|-------------| +| `build` | yes* | Build context — string (`"."`) or object (`{context, dockerfile}`) | +| `image` | yes* | Docker image to pull (e.g. `postgres:16-alpine`) | +| `port` | yes** | Container port the service listens on | +| `route` | no | URL path prefix for gateway routing (default: `/`) | +| `internal` | no | If `true`, not exposed through the proxy (e.g. databases) | +| `healthcheck` | no | `{path, interval?, retries?}` — polled before marking ready | +| `env` | no | Environment variables passed to the container | +| `volumes` | no | Additional volume mounts | +| `dev` | no | Dev mode overrides: `{image, command?, workdir?}` | + +\* Provide either `build` or `image`, not both. +\** Required unless `internal: true`. + +### Dev Mode + +Dev mode skips the Docker build and instead mounts your source code into a container running a dev server. Useful for hot reload during active development. + +To use dev mode, add a `dev` section to the service: + +```yaml +services: + app: + build: . + port: 3000 + dev: + image: node:20-alpine # base image with your runtime + command: npm run dev -- --host 0.0.0.0 # dev server command + workdir: /app # where source is mounted +``` + +Start with: + +```sh +cw preview start --initiative --project --branch --mode dev +``` + +The project directory is mounted at `workdir` (default `/app`). An anonymous volume is created for `node_modules` to prevent host/container conflicts. + +### Healthchecks + +If a service has a `healthcheck`, the preview waits for it to respond with HTTP 200 before reporting ready. Without a healthcheck, the service is considered ready as soon as the container starts. + +```yaml +healthcheck: + path: /health # required: endpoint to poll + interval: 5s # optional: time between checks (default: 5s) + retries: 10 # optional: max attempts before failing (default: 10) +``` + +### Auto-Start on Review + +When a phase transitions to `pending_review`, a preview is automatically started if: +- The initiative has exactly one registered project +- The project has a discoverable config (`.cw-preview.yml`, compose file, or Dockerfile) + +No manual `cw preview start` needed — just push your branch and move the phase to review. + ## Architecture ``` @@ -118,65 +264,13 @@ All preview containers get `cw.*` labels for metadata retrieval: - **`internal`** — per-preview bridge network for inter-service communication - Public services join both networks; internal services (e.g. databases) only join `internal` -## Configuration +## Config Discovery -Preview configuration is discovered from the project directory in this order: +See [Setting Up Preview Deployments](#setting-up-preview-deployments-for-a-project) above for the full config reference. Discovery order: -### 1. `.cw-preview.yml` (explicit CW config) - -```yaml -version: 1 -services: - frontend: - build: - context: . - dockerfile: apps/web/Dockerfile - port: 3000 - route: / - healthcheck: - path: / - interval: 5s - retries: 10 - env: - VITE_API_URL: /api - dev: - image: node:20-alpine - command: npm run dev -- --host 0.0.0.0 - workdir: /app - - backend: - build: - context: . - dockerfile: packages/api/Dockerfile - port: 8080 - route: /api - healthcheck: - path: /health - env: - DATABASE_URL: postgres://db:5432/app - - db: - image: postgres:16-alpine - port: 5432 - internal: true # not exposed through proxy - env: - POSTGRES_PASSWORD: preview -``` - -The `dev` section is optional per service. When present and mode is `dev`: -- `image` (required) — Docker image to run -- `command` — override entrypoint -- `workdir` — container working directory (default `/app`) - -In dev mode, the project directory is volume-mounted into the container and `node_modules` gets an anonymous volume to prevent host overwrite. - -### 2. `docker-compose.yml` / `compose.yml` (existing compose passthrough) - -If found, the existing compose file is used with gateway network injection. - -### 3. `Dockerfile` (single-service fallback) - -If only a Dockerfile exists, creates a single `app` service building from `.` with port 3000. +1. **`.cw-preview.yml`** — explicit CW preview config (recommended) +2. **`docker-compose.yml` / `compose.yml`** — existing compose file with gateway network injection +3. **`Dockerfile`** — single-service fallback (builds from `.`, assumes port 3000) ## Module Files