# base container
FROM python:3.12.7 AS base

# install uv from official image
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# set the working directory in the container
WORKDIR /app

# copy the dependency files into the container
COPY ./uv.lock ./
COPY ./pyproject.toml ./

# set environment variables for uv
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy

# install virtual environment and dependencies
# --group fb: dependencies of the non-wheel code the image carries (neops/fb
# function blocks, examples/) plus the git-pinned scrapli-cfg, which PyPI
# forbids in published metadata but the Cisco IOS scrapli plugin needs.
RUN uv sync --frozen --no-dev --group fb --no-install-project

# copy the app into the container
COPY ./neops_worker_sdk/ neops_worker_sdk/
COPY ./examples examples/
# The built-in function blocks (fb.base.neops.io/*) live here. Without them the
# published image has no function blocks to register, and only a bind mount of
# the source checkout makes the worker usable — see DIR_FUNCTION_BLOCKS, which
# is resolved relative to WORKDIR (`neops/fb` -> /app/neops/fb).
COPY ./neops neops/
# hatchling reads `readme = "README.md"`; the install below fails without it.
COPY ./README.md ./

# Install the project (the sync above is deps-only, for layer caching). Without
# this, `uv run` builds and installs it at every container start instead.
RUN uv sync --frozen --no-dev --group fb

# dev dependencies stage to avoid repeated installs in CI targets
FROM base AS deps-dev

# install dev and test dependencies once for CI stages, without installing the project itself.
# pytest lives in the `test` extra, not the dev group — same install as CI
# (.github/workflows/ci.yml).
RUN uv sync --frozen --group dev --group fb --extra test --no-install-project

# linter stage (optional CI target)
# Usage:
#   docker build --target linter -t neops-worker-sdk:lint .
FROM deps-dev AS linter

# run linters and type checks
RUN uv run ruff format --check neops_worker_sdk
RUN uv run ruff check neops_worker_sdk
RUN uv run pyrefly check

# mark success for CI aggregation
RUN echo "Linted successfully" > ./lint.txt

# test stage (optional CI target)
# Usage:
#   docker build --target test -t neops-worker-sdk:test .
FROM deps-dev AS test

# copy tests and the root fixtures (pytest config itself lives in pyproject.toml,
# already copied in `base`)
COPY ./tests tests/
COPY ./conftest.py ./conftest.py

# run unit tests — same invocation as CI; `addopts` already deselects remote_lab.
# (The former `-m "(sdk or testing) and ..."` selection matched nothing: no test
# in the repo carries the `sdk` or `testing` marker, so pytest exited 5.)
RUN uv run pytest -q

# mark success for CI aggregation
RUN echo "Tested successfully" > ./test.txt

# CI aggregator (optional CI target)
# Usage:
#   docker build --target run-ci -t neops-worker-sdk:ci .
FROM scratch AS run-ci
COPY --from=linter /app/lint.txt .
COPY --from=test /app/test.txt .

# app container (runtime)
FROM base

# --no-sync: the build already installed everything.
CMD ["uv", "run", "--no-sync", "neops_worker"]
