# syntax=docker/dockerfile:1.27
#
# Production-Image for {{appName}}.
#
# Server-Bundle variant — the runtime image doesn't carry the source tree
# or its node_modules any more, only:
#
#   dist/                  ← Client build (kumiko-build)
#   dist-server/           ← Server bundle (bun build) + minimal package.json
#   kumiko/migrations/     ← Checked-in SQL migrations applied by `kumiko schema apply`
#
# Build context: repository root (the full source tree is only used in the build stage).

ARG BUN_VERSION=1.4.0
{{#hasPrivateGhPackages}}
# Registry auth for @cosmicdriftgamestudio: CI passes the token as
# NPM_AUTH_TOKEN via --build-arg. Multi-stage ARG scoping needs the
# re-declaration inside the stage that uses it; this top-level ARG only
# makes it settable via `docker build`.
ARG NPM_AUTH_TOKEN=
{{/hasPrivateGhPackages}}
# Build identity — passed in by the CI workflow via --build-arg. Defaults
# for local container builds.
ARG BUILD_VERSION=dev
ARG BUILD_TIME=unknown

# ----- build: produces dist/ + dist-server/ ---------------------------------
FROM oven/bun:${BUN_VERSION}-alpine AS build
WORKDIR /app
{{#hasPrivateGhPackages}}
# bunfig.toml/.npmrc resolve the @cosmicdriftgamestudio scope via $GITHUB_TOKEN.
ARG NPM_AUTH_TOKEN
ENV GITHUB_TOKEN=${NPM_AUTH_TOKEN}
{{/hasPrivateGhPackages}}

{{#installFromFullTree}}
# file:/workspace:/link: deps (or a workspaces root) need the whole tree on
# disk for bun to resolve the lockfile — a partial COPY makes bun treat it
# as empty and rewrite it.
COPY . .
RUN bun install --frozen-lockfile
RUN bun run build
{{/installFromFullTree}}
{{#installFromManifests}}
# Manifests first for Docker layer cache — bun install only invalidates on
# dependency change, not on every source edit.
COPY {{installManifests}} ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
{{/installFromManifests}}

# ----- runtime: bun-alpine, knows only the bundle artefact ------------------
FROM oven/bun:${BUN_VERSION}-alpine AS runtime
# Global ARGs are invisible inside a stage until re-declared — without this,
# ENV BUILD_VERSION/BUILD_TIME below stay empty despite a correct --build-arg.
ARG BUILD_VERSION=dev
ARG BUILD_TIME=unknown
WORKDIR /app

RUN addgroup -S app && adduser -S app -G app

# Server bundle + its minimal package.json. `bun install --production`
# only pulls the actual externals.
COPY --from=build --chown=app:app /app/dist-server ./
RUN bun install --production

# Client build (static assets) — served by runProdApp.staticDir.
COPY --from=build --chown=app:app /app/dist ./dist

# Checked-in SQL migrations for the pre-deploy `kumiko schema apply` step.
# The shipped `kumiko-schema` bin reads `${INIT_CWD}/kumiko/migrations/*.sql`
# (see ENV INIT_CWD=/app below). kumiko/schema.ts is NOT needed at runtime
# (only generate reads it; apply is checksum-tracked SQL only).
COPY --from=build --chown=app:app /app/kumiko/migrations ./kumiko/migrations

# Container entrypoint — the platform may override the container command to
# inject runtime secrets, then execs `./start.sh`. We generate it inline so
# app-source-roots stay clean (no per-app start.sh duplication). Apps that
# don't go through a command-override still boot via the CMD at the bottom
# (`exec bun run server.js`) — start.sh is dead-code in that case.
RUN printf '#!/bin/sh\nset -e\nexec bun run server.js\n' > ./start.sh && chmod +x ./start.sh

{{#hasSeeds}}
# ES-Operations seed migrations — runtime-loaded via dynamic import. Bun
# does NOT bundle these into dist-server/server.js (await import on a
# dynamic path), so the seeds/ tree is copied raw. Bun's runtime
# transpiles the TS files on the fly.
#
# This block is emitted because scaffoldDeploy detected a `seeds/`
# directory at the source root. Apps without it skip the block entirely.
COPY --from=build --chown=app:app /app/seeds ./seeds
{{/hasSeeds}}

USER app

ENV NODE_ENV=production
# The framework assumes UTC.
ENV TZ=UTC
ENV PORT={{port}}
# The bundled kumiko.js CLI resolves its repo-relative paths via
# KUMIKO_REPO_ROOT (default: parent-of-import.meta.dir, which inside the
# bundle points to the wrong directory). /app is the app root + the
# node_modules parent here.
ENV KUMIKO_REPO_ROOT=/app
# INIT_CWD is the app workspace the schema-CLI runs against — that's where
# `kumiko/migrations/` lives. In the bundle container, /app is the workspace.
ENV INIT_CWD=/app
# Build identity in the runtime env so /api/version returns it.
# Built: SHA of the commit at image build time + ISO timestamp.
ENV BUILD_VERSION=$BUILD_VERSION
ENV BUILD_TIME=$BUILD_TIME

EXPOSE {{port}}

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
  CMD wget --quiet --spider "http://127.0.0.1:${PORT}/health" || exit 1

# exec → bun is PID 1 → SIGTERM reaches it directly → graceful shutdown.
CMD ["sh", "-c", "exec bun run server.js"]
