diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 263a8bd4..e1ed3524 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -63,6 +63,16 @@ jobs: repository: ${{ gitea.repository }} token: ${{ gitea.token }} + - name: Provide production env for build + run: | + # De Next.js-build bakt NEXT_PUBLIC_* in de client-bundle en + # valideert DATABASE_URL/HOTEL_NAME (zie src/env.ts — validatie + # overslaan is verboden voor productie). .env staat niet in git, + # dus kopieer de productie-.env van de host in de build-context. + # Hij belandt alleen in de wegwerp-builder-stage, niet in de + # runtime-image (die krijgt env via --env-file bij docker run). + cp /var/www/atom-nexst/.env .env + - name: Build image run: | # --network=host is vereist: deze host heeft Docker iptables @@ -76,13 +86,24 @@ jobs: - name: Deploy container run: | + # Maak poort 3002 vrij: stop zowel de vorige CI-container als de + # compose-container (beide draaien op het host-netwerk). docker stop epicnext-cms-app 2>/dev/null || true docker rm epicnext-cms-app 2>/dev/null || true + docker stop epicnext-cms 2>/dev/null || true + docker rm epicnext-cms 2>/dev/null || true + # Zelfde env + volumes als docker-compose.yml, zodat de CI-container + # functioneel gelijk is aan de compose-container die hij vervangt. docker run -d \ --name epicnext-cms-app \ --restart always \ --net=host \ + --env-file /var/www/atom-nexst/.env \ + -v /var/www/atom-nexst/public/nitro-assets:/app/public/nitro-assets \ + -v /var/www/atom-nexst/public/swf:/app/public/swf \ + -v /var/www/atom-nexst/storage:/app/storage \ + -v /var/www/Gamedata:/var/www/Gamedata \ epicnext-cms:latest docker image prune -f @@ -101,4 +122,8 @@ jobs: echo "ERROR: Health check failed" >&2 docker logs epicnext-cms-app --tail 50 >&2 || true + echo "Rolling back to compose container..." >&2 + docker stop epicnext-cms-app 2>/dev/null || true + docker rm epicnext-cms-app 2>/dev/null || true + docker compose -f /var/www/atom-nexst/docker-compose.yml up -d --no-build 2>&1 || true exit 1 diff --git a/Dockerfile b/Dockerfile index 41aca3f6..9c4e0051 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,12 @@ # --- Builder stage --- FROM node:26.8.1-bookworm-slim AS builder +# git is needed by next.config.ts (git rev-parse for deploymentId) and +# ca-certificates by package registries. Build runs on host network (see +# compose: iptables is disabled), so apt has registry access here. +RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates \ + && rm -rf /var/lib/apt/lists/* + # Install all three package managers so the build can pick whichever lockfile exists. RUN npm install -g pnpm@11.25.0 yarn diff --git a/src/lib/deploy-workflow-contract.test.ts b/src/lib/deploy-workflow-contract.test.ts index e869e929..6e22a70c 100644 --- a/src/lib/deploy-workflow-contract.test.ts +++ b/src/lib/deploy-workflow-contract.test.ts @@ -39,6 +39,24 @@ describe("deploy job", () => { expect(deployJob).toContain("--name epicnext-cms-app"); }); + it("provides production .env to the build", () => { + expect(deployJob).toContain("cp /var/www/atom-nexst/.env .env"); + }); + + it("runs container with production env and volumes", () => { + expect(deployJob).toContain("--env-file /var/www/atom-nexst/.env"); + expect(deployJob).toContain("/var/www/Gamedata:/var/www/Gamedata"); + expect(deployJob).toContain("/app/storage"); + }); + + it("frees port 3002 by stopping the compose container", () => { + expect(deployJob).toContain("docker stop epicnext-cms 2>/dev/null || true"); + }); + + it("rolls back to compose on health check failure", () => { + expect(deployJob).toContain("docker compose"); + }); + it("runs health check", () => { expect(deployJob).toContain("/api/health"); expect(deployJob).toContain('"database":true');