diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index df15692..06c5f18 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -20,6 +20,17 @@ jobs: git pull - docker compose up -d --build + # Build both images up front. `migrate` targets the Dockerfile's + # builder stage, which `app` also builds through, so the layers are + # shared and this costs no extra build time. The profile is named + # explicitly rather than relying on a service name activating it. + docker compose --profile tools build app migrate + + # Apply pending migrations before the new app serves traffic. This + # exits non-zero if a migration fails, failing the deploy rather than + # starting an app whose schema is behind its code. + docker compose --profile tools run --rm migrate + + docker compose up -d docker image prune -f diff --git a/README.md b/README.md index 2bb90d7..96fc3a3 100644 --- a/README.md +++ b/README.md @@ -112,11 +112,21 @@ Open http://localhost:3000 docker compose up --build -d ``` -After first run, apply migrations: +Pushing to `main` triggers the Gitea workflow in `.gitea/workflows/deploy.yml`, +which pulls, builds, **applies pending migrations, and only then starts the app**. +A failed migration fails the deploy rather than starting an app whose schema is +behind its code, so there is no manual migration step. + +Migrations run through the `migrate` service, which builds from the Dockerfile +`builder` stage. That matters: the production image ships runtime dependencies +only, and the Prisma CLI is a devDependency, so `docker compose exec app npx +prisma ...` would try to download Prisma inside the container at runtime. + +To run migrations by hand (or to seed on a first deploy): ```bash -docker compose exec app npx prisma migrate deploy -docker compose exec app npx prisma db seed +docker compose --profile tools run --rm migrate +docker compose --profile tools run --rm migrate npx prisma db seed ``` --- diff --git a/docker-compose.yml b/docker-compose.yml index 5c4648e..de35490 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,6 +21,34 @@ services: networks: - xbid + # One-off migration runner, applied by the deploy workflow before the app + # comes up. It builds from the Dockerfile's `builder` stage because the + # production image ships runtime dependencies only -- the Prisma CLI and its + # engines are devDependencies and are not in the standalone bundle. + # + # Behind a profile so `docker compose up` never starts it; the deploy targets + # it explicitly with `docker compose run --rm migrate`. + migrate: + build: + context: . + dockerfile: Dockerfile + target: builder + + environment: + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/xbid + + command: ["npx", "prisma", "migrate", "deploy"] + + depends_on: + postgres: + condition: service_healthy + + networks: + - xbid + + profiles: + - tools + app: build: context: .