Some checks failed
CI / lint (push) Successful in 32s
CI / notebooks-smoke (push) Failing after 1m39s
Deploy / notebooks (push) Successful in 6m26s
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 48s
Infra CI / zotero (push) Successful in 27s
Infra CI / docs (push) Successful in 14s
Infra CI / api (push) Successful in 24s
Infra CI / mc (push) Successful in 13s
CI / test (push) Failing after 16m28s
Deploy / report (push) Successful in 16s
Three gates so notebook breakage can't ship or linger silently again (spec: docs/superpowers/specs/2026-07-09-notebook-quality-gates-design.md): 1. nb_integration.py: runs notebooks headless via 'marimo export session', parses the JSON snapshots for cell errors, emits a report, exits 1 on unexpected failures. New ci.yml notebooks-smoke job runs the data-independent [ci_smoke] set (infra/marimo/nb-tests.toml) on every push; new nightly notebooks-integration.yml runs the full set inside the prod container against real data, filing failures as issues. 2. nb_fe_smoke.py: headless-browser gate that loads the editor and fails on any console/page error — the test that would have blocked the 'd is not a constructor' bundle. Wired into infra-ci.yml after the notebooks image build (all traffic over the docker socket; -v bind mounts silently arrive empty in CI). Verified: exit 0 on the fixed image and live prod, exit 1 on a synthetic crashing page. 3. nb_issue_filer.py + nb-watcher compose sidecar: one issue per error signature (notebook + ename + normalized message), rate-limited recurrence comments, auto-close after 24h quiet — the watcher is the single closing authority. Tails container logs via the docker socket (stdlib unix-socket HTTP, stream demux) and parses live session snapshots. First production tick filed 9 real deduplicated issues (#546-#554: a real skin_subs_explorer bug, missing pyzotero/trino, nessie/api connectivity) under the new 'notebooks' label. Also: notebooks.Dockerfile now lets corepack honor marimo's pinned packageManager instead of 'pnpm@latest' — the last floating input to the frontend build after the lockfile fix. Tests: 6 new unit-test groups (snapshot parsing, signature stability, dedup decisions); full suite green including notebook-layout policy (config placed in infra/marimo/, not notebooks/).
130 lines
5.0 KiB
Docker
130 lines
5.0 KiB
Docker
# syntax=docker/dockerfile:1
|
|
#
|
|
# Notebooks runtime — fhirworx-themed marimo on CUDA + Python 3.13.
|
|
#
|
|
# Stage 1 (fe): node + pnpm. Overlay fhirworx theme onto a pinned
|
|
# marimo source tree and compile frontend + lsp into
|
|
# marimo/_static/ and marimo/_lsp/.
|
|
# Stage 2 (wheel): uv builds a marimo wheel with the fhirworx bundle
|
|
# baked in.
|
|
# Stage 3 (final): CUDA runtime + Python stack; installs the wheel into
|
|
# the workspace venv.
|
|
#
|
|
# Iterate by editing infra/marimo/theme/**. BuildKit cache mounts keep
|
|
# pnpm and turbo warm between rebuilds, so CSS/icon edits land in under
|
|
# a minute after first bootstrap.
|
|
|
|
# renovate: datasource=github-tags depName=marimo-team/marimo extractVersion=^v?(?<version>.+)$
|
|
ARG MARIMO_VERSION=0.23.13
|
|
|
|
# ---- stage 1: frontend ------------------------------------------------------
|
|
|
|
FROM node:22-bookworm-slim AS fe
|
|
ARG MARIMO_VERSION
|
|
WORKDIR /src
|
|
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends git ca-certificates python3 jq \
|
|
&& rm -rf /var/lib/apt/lists/* \
|
|
&& corepack enable
|
|
# No `corepack prepare pnpm@latest`: the corepack shim resolves the exact
|
|
# pnpm version from marimo's package.json `packageManager` field at first
|
|
# use, so the package manager can't float between builds (the lockfile fix
|
|
# in apply-overlay.sh covers the dependency graph; this covers the tool).
|
|
|
|
# Shallow clone marimo at the pinned tag.
|
|
RUN git clone --depth 1 --branch ${MARIMO_VERSION} --filter=blob:none \
|
|
https://github.com/marimo-team/marimo /src
|
|
|
|
COPY infra/marimo/theme /overlay
|
|
RUN /overlay/scripts/apply-overlay.sh /src /overlay
|
|
|
|
RUN --mount=type=cache,target=/root/.cache/pnpm,sharing=locked \
|
|
pnpm install --no-frozen-lockfile
|
|
|
|
RUN --mount=type=cache,target=/root/.cache/turbo,sharing=locked \
|
|
--mount=type=cache,target=/src/frontend/node_modules/.cache,sharing=locked \
|
|
NODE_ENV=production pnpm turbo build --filter @marimo-team/frontend --output-logs=full
|
|
|
|
RUN --mount=type=cache,target=/root/.cache/turbo,sharing=locked \
|
|
NODE_ENV=production pnpm turbo build --filter @marimo-team/lsp --output-logs=full
|
|
|
|
RUN rm -rf marimo/_static marimo/_lsp \
|
|
&& mkdir -p marimo/_static marimo/_lsp \
|
|
&& cp -R frontend/dist/. marimo/_static/ \
|
|
&& rm -f marimo/_static/files/wasm-intro.py \
|
|
&& cp docs/_static/CLAUDE.md marimo/_static/CLAUDE.md 2>/dev/null || true \
|
|
&& cp packages/lsp/dist/index.cjs marimo/_lsp/ \
|
|
&& { [ -d packages/lsp/dist/copilot/dist ] \
|
|
&& cp -R packages/lsp/dist/copilot/dist/. marimo/_lsp/copilot/ \
|
|
|| true; }
|
|
|
|
# ---- stage 2: wheel ---------------------------------------------------------
|
|
|
|
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS wheel
|
|
WORKDIR /src
|
|
COPY --from=fe /src/ /src/
|
|
RUN uv build --wheel
|
|
|
|
# ---- stage 3: runtime -------------------------------------------------------
|
|
|
|
FROM nvidia/cuda:12.6.0-runtime-ubuntu24.04
|
|
|
|
ARG USERNAME=kert
|
|
ARG USER_UID=1000
|
|
ARG USER_GID=1000
|
|
ARG PYTHON_VERSION=3.13
|
|
|
|
# Local package registry (Gitea) — set via --build-arg to pull from mirror
|
|
ARG PYPI_INDEX_URL=""
|
|
|
|
ENV DEBIAN_FRONTEND=noninteractive \
|
|
HOME=/home/kert \
|
|
PATH="/home/kert/.local/bin:${PATH}" \
|
|
NVIDIA_VISIBLE_DEVICES=all \
|
|
NVIDIA_DRIVER_CAPABILITIES=compute,utility
|
|
|
|
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
|
|
curl ca-certificates git build-essential \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN groupmod -n ${USERNAME} ubuntu \
|
|
&& usermod -l ${USERNAME} -d /home/${USERNAME} -m -s /bin/bash ubuntu \
|
|
&& chown -R ${USER_UID}:${USER_GID} /home/${USERNAME}
|
|
|
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
COPY --from=ghcr.io/astral-sh/uv:latest /uvx /usr/local/bin/uvx
|
|
|
|
WORKDIR /home/${USERNAME}
|
|
|
|
# Bring in the fhirworx marimo wheel from the wheel stage.
|
|
COPY --from=wheel /src/dist/ /tmp/marimo-wheel/
|
|
|
|
# Install python + init workspace venv. Use the local wheel for marimo so
|
|
# the fhirworx frontend ships in the image; no upstream PyPI fetch for
|
|
# marimo itself.
|
|
RUN uv python install ${PYTHON_VERSION} \
|
|
&& uv init workspace --python ${PYTHON_VERSION} \
|
|
&& cd workspace \
|
|
&& MARIMO_WHL=$(ls /tmp/marimo-wheel/marimo-*.whl | head -1) \
|
|
&& uv add "${MARIMO_WHL}[recommended]" polars cudf-polars-cu12 pandas numpy pyarrow \
|
|
"pyiceberg[s3,pyarrow]>=0.7.0" "duckdb>=1.0.0" "narwhals>=1.0.0" "trino>=0.328.0" \
|
|
"sqlglot>=26.0.0" \
|
|
vega_datasets pyzotero obstore s3fs \
|
|
--extra-index-url https://pypi.nvidia.com
|
|
|
|
# Create marimo config directory with minimal defaults.
|
|
# Full config (marimo.toml, snippets, loch.css) is mounted at runtime
|
|
# from infra/marimo/ via compose.yml volumes.
|
|
RUN mkdir -p /home/${USERNAME}/.config/marimo
|
|
|
|
EXPOSE 2718
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
|
|
CMD curl -sf http://localhost:2718/health || exit 1
|
|
|
|
CMD ["uv", "run", "--project", "/home/kert/workspace", \
|
|
"marimo", "edit", \
|
|
"--host", "0.0.0.0", "--port", "2718", "--headless", "--no-token", \
|
|
"/home/kert/notebooks"]
|