# syntax=docker/dockerfile:1
# =============================================================================
# pg_trickle GHCR image — PostgreSQL 18.3 + pg_trickle pre-installed.
#
# Published to: ghcr.io/trickle-labs/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/trickle-labs/pg_trickle:<version>-pg18 \
#     -f Dockerfile.ghcr .
#
# Run (getting started):
#   docker run --rm -e POSTGRES_PASSWORD=secret \
#     ghcr.io/trickle-labs/pg_trickle:latest
#
# Scale up memory at runtime without rebuilding:
#   docker run --rm -e POSTGRES_PASSWORD=secret \
#     ghcr.io/trickle-labs/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 ──────────────────────────────────────
# OPS-10-03: Pinned to exact SHA256 digest for reproducibility.
# Run scripts/update_base_image_digests.sh to refresh quarterly.
FROM postgres:18.3-bookworm@sha256:80630f83606d8db77d30b3851b16a9f78be2d0d4dda6f7b82a1fdca5ebe3acba AS build-env

ARG VERSION=0.87.9

# 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.18.0

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

# ── Stage 2: Fetch dependencies (cached layer) ───────────────────────────────
# Cargo.toml + Cargo.lock are copied first with stub source files so that
# dependency fetching is cached independently of source changes.  The builder
# stage extends this stage, inheriting the populated registry cache.
FROM build-env AS build-deps

WORKDIR /build
COPY Cargo.toml Cargo.lock ./

# Minimal stubs so cargo can resolve the dependency graph.
RUN mkdir -p src/bin src/dvm/operators benches && \
    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() {}' > benches/scheduler_bench.rs && \
    echo 'fn main() {}' > benches/pgvector_bench.rs

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

# ── Stage 3: Build the extension ─────────────────────────────────────────────
# Extends build-deps so the fetched dependency cache is already warm.
FROM build-deps AS builder

# Overwrite stubs with real source code.  Cargo.toml/Cargo.lock are already
# present from build-deps and unchanged, so that layer stays cached.
COPY src/ src/
COPY pg_trickle.control ./

# Compile the extension.
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 ───────────────────────────────────────────────────
# OPS-10-03: Pinned to exact SHA256 digest for reproducibility.
# Run scripts/update_base_image_digests.sh to refresh quarterly.
FROM postgres:18.3-bookworm@sha256:80630f83606d8db77d30b3851b16a9f78be2d0d4dda6f7b82a1fdca5ebe3acba

ARG VERSION=0.87.9
ARG REPO_URL=https://github.com/trickle-labs/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="trickle-labs" \
      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
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=5 \
    CMD pg_isready -U postgres || exit 1
