# syntax=docker/dockerfile:1
# =============================================================================
# pg_trickle GHCR image — PostgreSQL 18.3 + pg_trickle pre-installed.
#
# Published to: ghcr.io/grove/pg_trickle
#
# Suitable for:
#   - Quick local evaluation:  docker run --rm -e POSTGRES_PASSWORD=pass ...
#   - CI/CD matrices:          replace postgres:18 with this image
#   - Kubernetes base images:  base for custom overlays
#
# NOT the same as the CNPG Image Volume Extension image (cnpg/Dockerfile.ext),
# which is scratch-based and extension-files only.
#
# Build (from project root):
#   docker build \
#     -t ghcr.io/grove/pg_trickle:0.13.0-pg18.3 \
#     -f Dockerfile.ghcr .
#
# Run (getting started):
#   docker run --rm -e POSTGRES_PASSWORD=secret \
#     ghcr.io/grove/pg_trickle:latest
#
# Scale up memory at runtime without rebuilding:
#   docker run --rm -e POSTGRES_PASSWORD=secret \
#     ghcr.io/grove/pg_trickle:latest \
#     -c shared_buffers=2GB -c work_mem=64MB -c effective_cache_size=6GB
#
# Default GUC settings are documented in docker/pg_trickle-defaults.conf.
# =============================================================================

# ── Stage 1: Prepare build environment ──────────────────────────────────────
FROM postgres:18.3-bookworm AS build-env

ARG VERSION=0.13.0

# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        curl \
        build-essential \
        libreadline-dev \
        zlib1g-dev \
        pkg-config \
        libssl-dev \
        libclang-dev \
        clang \
        postgresql-server-dev-18 \
        ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# Install Rust stable toolchain
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
    | sh -s -- -y --default-toolchain stable
ENV PATH="/root/.cargo/bin:${PATH}"

# Install cargo-pgrx (version must match Cargo.toml)
RUN cargo install --locked cargo-pgrx --version 0.17.0

# Initialise pgrx for PostgreSQL 18 using the system pg_config
RUN cargo pgrx init --pg18 /usr/bin/pg_config

# ── Stage 2: Compile dependencies (cached layer) ─────────────────────────────
FROM build-env AS build-deps

WORKDIR /build
COPY Cargo.toml Cargo.lock ./
COPY pgtrickle-tui/Cargo.toml pgtrickle-tui/Cargo.toml

# Minimal stubs so cargo can compile deps without the full source tree.
# These stubs will be replaced in the build stage below.
RUN mkdir -p src/bin src/dvm/operators benches pgtrickle-tui/src && \
    echo '#![allow(warnings)] fn main() {}' > src/bin/pgrx_embed.rs && \
    echo '#![allow(warnings)]' > src/lib.rs && \
    echo '' > src/dvm/mod.rs && \
    echo '' > src/dvm/operators/mod.rs && \
    echo '' > src/ivm.rs && \
    echo 'fn main() {}' > benches/refresh_bench.rs && \
    echo 'fn main() {}' > benches/diff_operators.rs && \
    echo 'fn main() {}' > pgtrickle-tui/src/main.rs

# Pre-fetch dependencies. Docker caches this layer independently.
# If only src/ changes on the next build, this layer is skipped, saving 10–15 min.
RUN --mount=type=cache,target=/root/.cargo/registry \
    --mount=type=cache,target=/root/.cargo/git \
    cargo fetch

# ── Stage 3: Build the extension ─────────────────────────────────────────────
FROM build-env AS builder

WORKDIR /build

# Copy source code and configuration
COPY Cargo.toml Cargo.lock ./
COPY pgtrickle-tui/Cargo.toml pgtrickle-tui/Cargo.toml
COPY src/ src/
COPY pg_trickle.control ./

# Create placeholder bench and workspace member files (required by Cargo.toml
# but not needed for extension package)
RUN mkdir -p benches pgtrickle-tui/src && \
    echo 'fn main() {}' > benches/diff_operators.rs && \
    echo 'fn main() {}' > benches/refresh_bench.rs && \
    echo 'fn main() {}' > pgtrickle-tui/src/main.rs

# Compile the extension. Cargo will automatically use cached dependencies
# from the build-deps stage's `cargo fetch` (stored in /root/.cargo).
RUN --mount=type=cache,target=/root/.cargo/registry \
    --mount=type=cache,target=/root/.cargo/git \
    cargo pgrx package --pg-config /usr/bin/pg_config && \
    mkdir -p /artefacts && \
    cp -r target/release/pg_trickle-pg18 /artefacts/

# ── Stage 4: Runtime image ───────────────────────────────────────────────────
FROM postgres:18.3-bookworm

ARG VERSION=0.13.0
ARG REPO_URL=https://github.com/grove/pg-trickle

LABEL org.opencontainers.image.title="pg_trickle" \
      org.opencontainers.image.description="PostgreSQL 18.3 with pg_trickle streaming tables and IVM pre-installed" \
      org.opencontainers.image.version="${VERSION}" \
      org.opencontainers.image.licenses="Apache-2.0" \
      org.opencontainers.image.source="${REPO_URL}" \
      org.opencontainers.image.documentation="${REPO_URL}/blob/main/docs/GETTING_STARTED.md" \
      org.opencontainers.image.vendor="grove" \
      org.opencontainers.image.base.name="docker.io/library/postgres:18.3-bookworm"

# Copy extension artifacts from builder
COPY --from=builder \
    /artefacts/pg_trickle-pg18/usr/share/postgresql/18/extension/ \
    /usr/share/postgresql/18/extension/

COPY --from=builder \
    /artefacts/pg_trickle-pg18/usr/lib/postgresql/18/lib/ \
    /usr/lib/postgresql/18/lib/

# Configure pg_trickle in the default postgresql.conf template so any
# cluster created from this image has the extension auto-loaded with
# sensible defaults.  The full set of defaults is documented in
# docker/pg_trickle-defaults.conf (included in the build context).
COPY docker/pg_trickle-defaults.conf /tmp/pg_trickle-defaults.conf
RUN echo "" >> /usr/share/postgresql/postgresql.conf.sample && \
    cat /tmp/pg_trickle-defaults.conf >> /usr/share/postgresql/postgresql.conf.sample && \
    rm /tmp/pg_trickle-defaults.conf

# Create the extension on the default 'postgres' database during initdb so
# the background worker launcher finds it immediately on first startup.
RUN mkdir -p /docker-entrypoint-initdb.d && \
    echo "CREATE EXTENSION IF NOT EXISTS pg_trickle CASCADE;" \
    > /docker-entrypoint-initdb.d/00-pg-trickle.sql

# Verify artifacts are in place
RUN ls -la /usr/share/postgresql/18/extension/pg_trickle* && \
    ls -la /usr/lib/postgresql/18/lib/pg_trickle*

EXPOSE 5432
