diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index f8d4f1f..7510475 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -5,6 +5,7 @@ on: pull_request: env: + BASE_URL: https://guide.sudloh.com REGISTRY_IMAGE: registry.neko-piranha.ts.net/astral/buzz-sheet DEPLOY_NAMESPACE: buzz-sheet KUBE_API_SERVER: https://100.112.189.33:6443/ @@ -60,6 +61,7 @@ jobs: run: | docker build \ --target app \ + --build-arg BASE_URL="$BASE_URL" \ --build-arg NEXT_DEPLOYMENT_ID=${{ gitea.sha }} \ --build-arg VCS_REF=${{ gitea.sha }} \ --tag ${{ env.REGISTRY_IMAGE }}:${{ gitea.sha }} \ diff --git a/Dockerfile b/Dockerfile index 7d060d3..918e1f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,8 @@ RUN bun build scripts/outbox-worker.ts \ FROM node:22-bookworm-slim AS next-builder WORKDIR /app ARG NEXT_DEPLOYMENT_ID=container-build +ARG BASE_URL +ENV BASE_URL=${BASE_URL} ENV NEXT_DEPLOYMENT_ID=${NEXT_DEPLOYMENT_ID} ENV NEXT_TELEMETRY_DISABLED=1 COPY --from=dependencies /app/node_modules ./node_modules diff --git a/README.md b/README.md index 9cfd6d9..99bee47 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ cp .env.example .env `.env.example` contains placeholders only. Configure `.env` yourself; it is ignored by Git and must never be committed. `BETTER_AUTH_URL` must exactly -match the application origin. Existing administrators can create additional +match the application origin. Set `BASE_URL` to the public site origin for SEO +metadata, sitemap, and robots.txt. Existing administrators can create additional credential accounts from `/admin/register`; public registration is disabled. Prepare the database and start the application: @@ -153,6 +154,7 @@ with the same identity. ```bash docker build \ --target app \ + --build-arg BASE_URL=https://guide.sudloh.com \ --build-arg NEXT_DEPLOYMENT_ID= \ --build-arg VCS_REF= \ --tag buzz-sheet: \ @@ -166,6 +168,9 @@ docker build \ ``` The runtime images do not contain local `.env` files. +`BASE_URL` is required during the Next.js build and at runtime. CI supplies the +build argument, and the Kubernetes ConfigMap supplies the runtime value. Keep +both values aligned when changing the public site origin. ## Kubernetes diff --git a/k8s/base/configmap.yaml b/k8s/base/configmap.yaml index f42367c..cf5bdd5 100644 --- a/k8s/base/configmap.yaml +++ b/k8s/base/configmap.yaml @@ -5,6 +5,7 @@ metadata: labels: app.kubernetes.io/name: buzz-sheet data: + BASE_URL: https://guide.sudloh.com BETTER_AUTH_URL: https://guide.sudloh.com BUZZ_DEMO_MODE: "false" DATABASE_POOL_SIZE: "10" diff --git a/tests/deployment-contract.test.ts b/tests/deployment-contract.test.ts index e155bf7..18e5c44 100644 --- a/tests/deployment-contract.test.ts +++ b/tests/deployment-contract.test.ts @@ -91,6 +91,7 @@ describe("production deployment contract", () => { expect(dockerfile.match(/^USER 1000:1000$/gmu)).toHaveLength(2); expect(dockerfile).toContain('ENTRYPOINT ["bun", "scripts/migrate.ts"]'); expect(dockerfile).toContain('CMD ["bun", "server.js"]'); + expect(dockerfile).toContain("ARG BASE_URL\nENV BASE_URL=${BASE_URL}"); expect(dockerfile).toContain("backend/discord.ts"); expect(dockerfile).toContain("./worker/discord.js"); }); @@ -104,6 +105,7 @@ describe("production deployment contract", () => { expect(workflow).toContain("bun run lint"); expect(workflow).toContain("kubectl kustomize k8s/"); expect(workflow).toContain("--target app"); + expect(workflow).toContain('--build-arg BASE_URL="$BASE_URL"'); expect(workflow).toContain("--target migration"); expect(workflow).not.toContain("platforms: linux/arm64"); expect(workflow).not.toMatch(/docker\/setup-qemu-action|docker\/setup-buildx-action|docker\/login-action/iu);