# syntax=docker/dockerfile:1
# Generated by scripts/generate_build_files.py. Edit docker/templates/Dockerfile
# and docker/images.toml, then regenerate.

FROM python:3.14-slim AS builder
WORKDIR /src
# Expensive dependency layers precede VERSION and the source COPY.
# CI refreshes them on releases; ordinary commits reuse them.
ARG DEPS_REFRESH=""
RUN set -eux; \
    : "deps-refresh=${DEPS_REFRESH}"; \
    retry() { n=0; until "$@"; do n=$((n+1)); if [ "$n" -ge 5 ]; then return 1; fi; echo "retry $n: $*"; sleep $((n*5)); done; }; \
    retry apt-get -o Acquire::Retries=5 -o APT::Update::Error-Mode=any update; \
    retry apt-get -o Acquire::Retries=5 install -y --no-install-recommends build-essential libffi-dev zlib1g-dev git; \
    rm -rf /var/lib/apt/lists/*

# Record the distro interpreter or install the opt-in amd64v3 runtime.
ARG PYTHON_VARIANT=baseline
COPY docker/python_runtime.py /tmp/deps/python_runtime.py
RUN python /tmp/deps/python_runtime.py --variant "$PYTHON_VARIANT" --libc gnu --prefix /opt/python-runtime

# Resolve dependencies from pyproject; the wheelhouse matches the target libc.
ARG ZEROCONF_VERSION=""
COPY pyproject.toml /tmp/deps/pyproject.toml
COPY docker/extract_deps.py /tmp/deps/extract_deps.py
COPY docker/wheelhouse/glibc/ /tmp/deps/pqwheels/
RUN set -eux; \
    retry() { n=0; until "$@"; do n=$((n+1)); if [ "$n" -ge 5 ]; then return 1; fi; echo "retry $n: $*"; sleep $((n*5)); done; }; \
    "$(cat /opt/python-runtime/python-path)" -m venv /opt/venv; \
    retry /opt/venv/bin/pip install --no-cache-dir --upgrade pip; \
    /opt/venv/bin/python /tmp/deps/extract_deps.py /tmp/deps/pyproject.toml /tmp/deps/pqwheels; \
    retry /opt/venv/bin/pip install --no-cache-dir --timeout 60 --find-links /tmp/deps/pqwheels --only-binary cryptography -r /tmp/deps/requirements.txt; \
    "$(cat /opt/python-runtime/python-path)" -m venv /tmp/deps/buildenv; \
    retry /tmp/deps/buildenv/bin/pip install --no-cache-dir --timeout 60 -r /tmp/deps/build-requires.txt
RUN /opt/venv/bin/python -c 'from nacl.public import PrivateKey, SealedBox; k = PrivateKey.generate(); m = b"cronstable push self-test"; assert SealedBox(k).decrypt(SealedBox(k.public_key).encrypt(m)) == m; import importlib.util as u; assert u.find_spec("cryptography") is None or u.find_spec("cryptography.hazmat.primitives.hpke") is not None, "cryptography is too old to seal xwing"; import zeroconf, zeroconf.asyncio; print("push and discovery extras verified")'

# Optional acceleration: verify the install, falling back to stdlib JSON.
COPY docker/install_orjson.sh /tmp/deps/install_orjson.sh
COPY pyinstaller/verify_extra.py /tmp/deps/verify_extra.py
RUN set -eux; \
    RUST_SETUP="apt-get -o Acquire::Retries=5 -o APT::Update::Error-Mode=any update \
        && apt-get -o Acquire::Retries=5 install -y --no-install-recommends curl ca-certificates \
        && curl --proto =https --tlsv1.2 -sSf https://sh.rustup.rs | env CARGO_HOME=/opt/cargo RUSTUP_HOME=/opt/rustup sh -s -- -y --default-toolchain stable --profile minimal --no-modify-path" \
    sh /tmp/deps/install_orjson.sh "orjson>=3.11.6"; \
    rm -rf /var/lib/apt/lists/*

# Only these project-install layers depend on this commit and its version.
ARG VERSION=""
COPY . .
RUN set -eux; \
    if [ -n "$VERSION" ]; then export SETUPTOOLS_SCM_PRETEND_VERSION="$VERSION"; fi; \
    /tmp/deps/buildenv/bin/pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/deps/wheelhouse .; \
    /opt/venv/bin/pip install --no-cache-dir --no-deps /tmp/deps/wheelhouse/cronstable-*.whl; \
    /opt/venv/bin/pip check
RUN set -eux; \
    if /opt/venv/bin/python -c 'import cryptography' 2>/dev/null; then \
        suites=$(/opt/venv/bin/python -m cronstable --sealable-suites); \
        echo "sealable suites: $suites"; \
        echo "$suites" | grep -qx xwing; \
    fi

# pip is unnecessary in the runtime image.
RUN /opt/venv/bin/pip uninstall -y pip || true

# Runtime packages must match the builder interpreter and shared libraries.
FROM python:3.14-slim
LABEL org.opencontainers.image.title="cronstable" \
      org.opencontainers.image.description="A modern, rootless-container-friendly cron replacement." \
      org.opencontainers.image.source="https://github.com/ptweezy/cronstable" \
      org.opencontainers.image.url="https://github.com/ptweezy/cronstable" \
      org.opencontainers.image.documentation="https://github.com/ptweezy/cronstable/wiki" \
      org.opencontainers.image.authors="Parker Loflin <parker@cronstable.dev>" \
      org.opencontainers.image.vendor="Parker Loflin" \
      org.opencontainers.image.licenses="MIT"
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PATH="/opt/venv/bin:$PATH"
COPY --from=builder /opt/python-runtime /opt/python-runtime
COPY --from=builder /opt/venv /opt/venv
# Prove the final stage loads the selected interpreter and its libraries.
RUN ["/opt/venv/bin/python", "-m", "cronstable", "--version"]

# Run without root; the runtime also supports a read-only filesystem.
USER 65534:65534
ENTRYPOINT ["cronstable"]
CMD ["-c", "/etc/cronstable.d"]
