# syntax=docker/dockerfile:1.7
#
# Default build is CGO-free (NATS + JSON) — no librdkafka, gcc, or musl-dev, so
# it builds in a fraction of the time and cross-compiles to arm64/amd64 cleanly.
# BuildKit cache mounts keep the module + compile caches warm across builds.
#
# The builder always runs on the build host ($BUILDPLATFORM) and cross-compiles
# to $TARGETARCH, so multi-arch CI builds never run the Go compiler under QEMU.
#
# To include the optional Kafka backend, build with --build-arg GO_TAGS=kafka
# (adds librdkafka + CGO; slower, and CGO cannot cross-compile — build each arch
# on a native runner). Runtime selection is still by env
# (EVENTBUS_PROVIDER / CODEC_PROVIDER).
FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS builder

ARG GO_TAGS=""
ARG TARGETOS TARGETARCH
RUN apk add --no-cache git ca-certificates && \
    if echo "$GO_TAGS" | grep -qw kafka; then apk add --no-cache gcc musl-dev librdkafka-dev; fi

WORKDIR /app
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod go mod download

COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    set -eux; \
    if echo "$GO_TAGS" | grep -qw kafka; then CGO=1; TAGS="musl kafka"; else CGO=0; TAGS=""; fi; \
    CGO_ENABLED=$CGO GOOS=$TARGETOS GOARCH=$TARGETARCH go build -tags "$TAGS" -ldflags="-s -w" -o /out/backend ./cmd/backend; \
    CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" -o /out/seed ./cmd/seed; \
    CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" -o /out/migrate ./cmd/migrate; \
    CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" -o /out/warmblyctl ./cmd/warmblyctl

# Runtime stage
FROM alpine:3.23

ARG GO_TAGS=""
RUN apk add --no-cache ca-certificates tzdata && \
    if echo "$GO_TAGS" | grep -qw kafka; then apk add --no-cache librdkafka; fi && \
    adduser -D -u 1000 warmbly

# BLOB_FS_ROOT's default mount point, owned by the user the process runs as.
# Docker seeds a fresh named volume from the image, so the directory has to
# exist here with the right owner; otherwise Docker creates the mount point
# root-owned, the non-root process cannot write to it, and the first send fails
# with "mkdir /data/blobs/emails: permission denied".
RUN mkdir -p /data/blobs && chown -R warmbly:warmbly /data

COPY --from=builder /out/backend /app/backend
COPY --from=builder /out/seed /app/seed
COPY --from=builder /out/migrate /app/migrate

# The operator CLI goes on PATH, not /app, so the documented recovery command is
# `docker compose exec backend warmblyctl status` and not a path.
COPY --from=builder /out/warmblyctl /usr/local/bin/warmblyctl

# Installer script the worker orchestrator uploads + runs over SSH, and serves
# at GET /worker-install.sh. The mode is explicit because COPY otherwise keeps
# the checkout's: on a filesystem without POSIX permissions that is 0700, and
# the backend runs as uid 1000, so serving the installer fails with a 500.
COPY --chmod=755 scripts/install-worker.sh /app/scripts/install-worker.sh

USER warmbly
EXPOSE 8080

# 127.0.0.1, not localhost: busybox wget tries ::1 first but the server binds IPv4.
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
  CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8080/health || exit 1

ENTRYPOINT ["/app/backend"]
