# syntax=docker/dockerfile:1
#
# CI test image — Python 3 + Node.js + OCaml 5.2 + dune.
#
# Build chain:
#   1. Compile OCaml from checked-in sx_ref.ml  — produces sx_server.exe
#   2. Bootstrap JS (sx-browser.js)             — OcamlSync transpiler → JS
#   3. Re-bootstrap OCaml (sx_ref.ml)           — OcamlSync transpiler → OCaml
#   4. Recompile OCaml with fresh sx_ref.ml     — final native binary
#
# Test suites (run at CMD):
#   - JS standard + full tests         — Node
#   - OCaml spec tests                 — native binary
#   - OCaml bridge integration tests   — Python + OCaml subprocess
#
# Usage:
#   docker build -f .gitea/Dockerfile.test -t sx-test .
#   docker run --rm sx-test

FROM ocaml/opam:debian-12-ocaml-5.2

USER root
RUN apt-get update && apt-get install -y --no-install-recommends \
      python3 ca-certificates curl xz-utils \
    && rm -rf /var/lib/apt/lists/*
# Node.js — direct binary (avoids the massive Debian nodejs dep tree)
RUN NODE_VERSION=22.22.1 \
    && ARCH=$(dpkg --print-architecture | sed 's/amd64/x64/;s/arm64/arm64/;s/armhf/armv7l/') \
    && curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${ARCH}.tar.xz" \
       | tar -xJ --strip-components=1 -C /usr/local
USER opam

# Install dune into the opam switch
RUN opam install dune -y

# Bake the opam switch PATH into the image so dune/ocamlfind work in RUN
ENV PATH="/home/opam/.opam/5.2/bin:${PATH}"

WORKDIR /home/opam/project

# Copy OCaml sources first (changes less often → better caching)
COPY --chown=opam:opam hosts/ocaml/dune-project ./hosts/ocaml/
COPY --chown=opam:opam hosts/ocaml/lib/         ./hosts/ocaml/lib/
COPY --chown=opam:opam hosts/ocaml/bin/         ./hosts/ocaml/bin/

# Copy spec, lib, web, shared (needed by bootstrappers + tests)
COPY --chown=opam:opam spec/           ./spec/
COPY --chown=opam:opam lib/            ./lib/
COPY --chown=opam:opam web/            ./web/
COPY --chown=opam:opam shared/sx/      ./shared/sx/
COPY --chown=opam:opam shared/__init__.py ./shared/__init__.py

# Copy JS host (bootstrapper + test runner)
COPY --chown=opam:opam hosts/javascript/ ./hosts/javascript/

# Copy OCaml host (bootstrapper + transpiler)
COPY --chown=opam:opam hosts/ocaml/bootstrap.py   ./hosts/ocaml/bootstrap.py
COPY --chown=opam:opam hosts/ocaml/transpiler.sx   ./hosts/ocaml/transpiler.sx

# Create output directory for JS builds
RUN mkdir -p shared/static/scripts

# Step 1: Compile OCaml from checked-in sx_ref.ml
#   → produces sx_server.exe (needed by both JS and OCaml bootstrappers)
RUN cd hosts/ocaml && dune build

# Step 2: Bootstrap JS (uses sx_server.exe via OcamlSync)
RUN python3 hosts/javascript/cli.py \
      --output shared/static/scripts/sx-browser.js \
    && python3 hosts/javascript/cli.py \
      --extensions continuations --spec-modules types \
      --output shared/static/scripts/sx-full-test.js

# Step 3: Re-bootstrap OCaml (transpile current spec → fresh sx_ref.ml)
RUN python3 hosts/ocaml/bootstrap.py \
      --output hosts/ocaml/lib/sx_ref.ml

# Step 4: Recompile OCaml with freshly bootstrapped sx_ref.ml
RUN cd hosts/ocaml && dune build

# Default: run all tests
COPY --chown=opam:opam .gitea/run-ci-tests.sh ./run-ci-tests.sh
RUN chmod +x run-ci-tests.sh

CMD ["./run-ci-tests.sh"]
