|
| 1 | +FROM ubuntu:24.04 |
| 2 | + |
| 3 | +ENV DEBIAN_FRONTEND=noninteractive |
| 4 | +ENV PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright |
| 5 | +ENV PNPM_STORE_DIR=/opt/pnpm-store |
| 6 | + |
| 7 | +# 1. OS + base tools |
| 8 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 9 | + curl git ca-certificates gnupg \ |
| 10 | + build-essential libffi-dev libssl-dev tini \ |
| 11 | + && rm -rf /var/lib/apt/lists/* |
| 12 | + |
| 13 | +# 2. uv (pinned — bump when needed, not on a schedule) |
| 14 | +COPY --from=ghcr.io/astral-sh/uv:0.6.6 /uv /usr/local/bin/uv |
| 15 | + |
| 16 | +# 3. Python 3.11-3.14 via uv (no deadsnakes PPA needed) |
| 17 | +RUN uv python install 3.11 3.12 3.13 3.14 |
| 18 | + |
| 19 | +# 4. Node 22 LTS + pnpm 9.10.0 (pinned) |
| 20 | +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ |
| 21 | + && apt-get install -y --no-install-recommends nodejs \ |
| 22 | + && rm -rf /var/lib/apt/lists/* \ |
| 23 | + && corepack enable \ |
| 24 | + && corepack prepare pnpm@9.10.0 --activate |
| 25 | + |
| 26 | +# 5. JS deps — populate pnpm content-addressable store |
| 27 | +# Reproduces the packages/ workspace structure so pnpm install works. |
| 28 | +# At runtime, pnpm install is ~50ms (just creates hard links from the store). |
| 29 | +WORKDIR /build-js |
| 30 | +COPY packages/pnpm-lock.yaml packages/pnpm-workspace.yaml packages/package.json ./ |
| 31 | +COPY packages/buckaroo-js-core/package.json ./buckaroo-js-core/ |
| 32 | +COPY packages/js/package.json ./js/ |
| 33 | +RUN pnpm install --frozen-lockfile --store-dir /opt/pnpm-store |
| 34 | + |
| 35 | +# 6. Python deps — one venv per Python version, all extras, no project install |
| 36 | +# At runtime, `uv sync` installs only buckaroo itself (editable), which is instant. |
| 37 | +WORKDIR /build-py |
| 38 | +COPY pyproject.toml uv.lock ./ |
| 39 | +RUN for v in 3.11 3.12 3.13 3.14; do \ |
| 40 | + uv venv /opt/venvs/$v --python $v && \ |
| 41 | + UV_PROJECT_ENVIRONMENT=/opt/venvs/$v \ |
| 42 | + uv sync --locked --dev --all-extras --no-install-project; \ |
| 43 | +done |
| 44 | + |
| 45 | +# 7. Playwright chromium — install system deps + browser for Python playwright. |
| 46 | +# JS playwright (pnpm exec playwright) uses the same PLAYWRIGHT_BROWSERS_PATH, |
| 47 | +# so it will find the same browser or install its version alongside it. |
| 48 | +RUN /opt/venvs/3.13/bin/playwright install --with-deps chromium |
| 49 | +RUN cd /build-js/buckaroo-js-core && pnpm exec playwright install chromium |
| 50 | + |
| 51 | +# 8. Bake CI runner scripts into the image at a stable path so they survive |
| 52 | +# `git checkout` of arbitrary SHAs inside /repo at runtime. |
| 53 | +COPY ci/hetzner/run-ci.sh ci/hetzner/lib/ /opt/ci-runner/ |
| 54 | +COPY scripts/test_playwright_jupyter_parallel.sh /opt/ci-runner/ |
| 55 | +ARG GIT_SHA=unknown |
| 56 | +RUN echo "$GIT_SHA" > /opt/ci-runner/VERSION && \ |
| 57 | + chmod +x /opt/ci-runner/run-ci.sh /opt/ci-runner/test_playwright_jupyter_parallel.sh |
| 58 | + |
| 59 | +# Allow JupyterLab to start as root (container runs as root). |
| 60 | +# This avoids needing --allow-root in every script that starts Jupyter. |
| 61 | +RUN mkdir -p /root/.jupyter && \ |
| 62 | + echo "c.ServerApp.allow_root = True" >> /root/.jupyter/jupyter_lab_config.py |
| 63 | + |
| 64 | +# Source code is bind-mounted at /repo at runtime — not baked in. |
| 65 | +# Allow git to operate on the bind-mounted repo (owned by ci on host, root in container). |
| 66 | +RUN git config --system --add safe.directory /repo |
| 67 | +WORKDIR /repo |
| 68 | +# tini as PID 1 reaps zombie processes from docker exec'd CI runs. |
| 69 | +# Without it, sleep-infinity PID 1 doesn't call wait(), zombies accumulate, |
| 70 | +# and back-to-back CI runs fail. |
| 71 | +ENTRYPOINT ["/usr/bin/tini", "--"] |
| 72 | +CMD ["sleep", "infinity"] |
0 commit comments