dc2eb47297
- Added optional slot_uid handling to push requests and git operations, validating IDs 1..65535. - Passed slot-specific subprocess kwargs into git helpers, including safe.directory, HOME, user/group and umask. - Injected slot-safe repo env helpers to scrub secrets, force git identity, and disable terminal prompts. - Adjusted workspace and cache permissioning so slot users own workspaces with targeted chmod/chown behavior. - Added tests for slot UID propagation, safe-directory env, and cross-slot push/retry behavior in unit and e2e suites.
133 lines
5.4 KiB
Docker
133 lines
5.4 KiB
Docker
# syntax=docker/dockerfile:1.7
|
|
###############################################################################
|
|
# roboomp — orchestrator image
|
|
#
|
|
# Build is split across three stages:
|
|
#
|
|
# 1) pi-artifacts — pull a pre-built `oh-my-pi/artifacts:dev` image (built
|
|
# separately from /work/pi/Dockerfile, see `bun run pi-artifacts`):
|
|
# - pi_natives.linux-<arch>.node → /opt/bun/bin/ (the pi loader probes here)
|
|
# - omp_rpc-*.whl → pip install
|
|
# 2) web-builder — Bun + Vite compile the SolidJS dashboard bundle from
|
|
# the `web/` workspace into `web/dist/`.
|
|
# 3) runtime — slim Python 3.12 image that copies in (1) the natives
|
|
# + wheel, (2) the dashboard bundle, and (3) the roboomp source.
|
|
#
|
|
# At runtime the full pi checkout is mounted read-only at /work/pi so `omp`
|
|
# (the Bun shim below) executes the coding-agent source directly. The image
|
|
# itself stays slim: no rust compile, no pi source tree, no node_modules.
|
|
###############################################################################
|
|
|
|
ARG PI_ARTIFACTS_IMAGE=oh-my-pi/artifacts:dev
|
|
|
|
############################
|
|
# 1) pi-artifacts — pull the pre-built natives + omp-rpc wheel.
|
|
############################
|
|
FROM ${PI_ARTIFACTS_IMAGE} AS pi-artifacts
|
|
|
|
############################
|
|
# 2) web-builder — Bun + Vite, builds the SolidJS dashboard bundle.
|
|
############################
|
|
FROM oven/bun:1.3.14-slim AS web-builder
|
|
WORKDIR /work
|
|
# The repo is a Bun workspace (`workspaces: ["web"]` at the root). Install
|
|
# from the root lockfile so the web subpackage resolves against the same
|
|
# pinned dependency graph used locally.
|
|
COPY package.json bun.lock ./
|
|
COPY web/package.json ./web/package.json
|
|
RUN bun install --frozen-lockfile
|
|
COPY web/ ./web/
|
|
RUN bun --cwd=web run build
|
|
|
|
############################
|
|
# 3) runtime — slim image with everything roboomp needs at boot.
|
|
############################
|
|
FROM python:3.12-slim-bookworm AS runtime
|
|
|
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
PYTHONUNBUFFERED=1 \
|
|
PIP_NO_CACHE_DIR=1 \
|
|
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
|
BUN_INSTALL=/opt/bun \
|
|
PI_ROOT=/work/pi \
|
|
# Persistent build caches under the /data volume so cargo target and
|
|
# rustup toolchains are shared across every per-issue worktree and
|
|
# survive container restarts. Bun's install cache is deliberately
|
|
# workspace-private at runtime; bun chmod/chown behavior makes a shared
|
|
# cross-slot cache unreliable.
|
|
CARGO_HOME=/data/cache/cargo \
|
|
CARGO_TARGET_DIR=/data/cache/cargo-target \
|
|
RUSTUP_HOME=/data/cache/rustup \
|
|
PATH=/opt/bun/bin:/usr/local/cargo/bin:/usr/local/bin:/usr/bin:/bin
|
|
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
git curl ca-certificates unzip openssh-client tini sqlite3 \
|
|
build-essential pkg-config libssl-dev \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
ARG BUN_VERSION=1.3.14
|
|
RUN curl -fsSL https://bun.sh/install | bash -s "bun-v${BUN_VERSION}" \
|
|
&& /opt/bun/bin/bun --version
|
|
|
|
# Rustup launcher. Install the cargo/rustc/rustup proxies into a fixed
|
|
# image path; the real toolchain is *not* baked in — it's installed
|
|
# lazily into RUSTUP_HOME (=/data/cache/rustup) on the first `cargo`
|
|
# invocation inside a worktree, driven by pi's rust-toolchain.toml.
|
|
# That keeps the image small while sharing the toolchain across reboots.
|
|
RUN curl -fsSL https://sh.rustup.rs -o /tmp/rustup-init.sh \
|
|
&& CARGO_HOME=/usr/local/cargo RUSTUP_HOME=/usr/local/rustup-bootstrap \
|
|
sh /tmp/rustup-init.sh -y --no-modify-path --default-toolchain none --profile minimal \
|
|
&& rm -f /tmp/rustup-init.sh \
|
|
&& rm -rf /usr/local/rustup-bootstrap \
|
|
&& /usr/local/cargo/bin/rustup --version
|
|
|
|
# pi-natives addon: pi's loader probes /opt/bun/bin as a fallback path.
|
|
COPY --from=pi-artifacts /out/pi_natives.linux-*.node /opt/bun/bin/
|
|
|
|
# omp-rpc Python wheel.
|
|
COPY --from=pi-artifacts /out/*.whl /tmp/wheels/
|
|
RUN pip install /tmp/wheels/omp_rpc-*.whl && rm -rf /tmp/wheels
|
|
|
|
WORKDIR /app
|
|
|
|
# `omp` shim — calls into the mounted pi checkout via Bun.
|
|
RUN printf '%s\n' \
|
|
'#!/usr/bin/env bash' \
|
|
'set -euo pipefail' \
|
|
': "${PI_ROOT:=/work/pi}"' \
|
|
'if [ ! -d "$PI_ROOT/packages/coding-agent" ]; then' \
|
|
' echo "roboomp: PI_ROOT=$PI_ROOT does not look like a pi checkout" >&2' \
|
|
' exit 127' \
|
|
'fi' \
|
|
'exec bun "$PI_ROOT/packages/coding-agent/src/cli.ts" "$@"' \
|
|
> /usr/local/bin/omp \
|
|
&& chmod +x /usr/local/bin/omp
|
|
|
|
# roboomp itself. Drop the Vite-built dashboard into the package tree before
|
|
# `pip install` so it lands in the installed wheel (`static/**/*` is declared
|
|
# as package-data in pyproject.toml).
|
|
COPY pyproject.toml ./
|
|
COPY src/ ./src/
|
|
COPY --from=web-builder /work/web/dist/ ./src/robomp/static/
|
|
RUN pip install --upgrade pip \
|
|
&& pip install \
|
|
"fastapi>=0.112" "uvicorn[standard]>=0.30" "httpx>=0.27" \
|
|
"pydantic>=2.6" "pydantic-settings>=2.2" "python-dotenv>=1.0" \
|
|
"click>=8.1" \
|
|
&& pip install --no-deps .
|
|
|
|
RUN mkdir -p /srv/agent-home/.agent /srv/agent-home/.omp/agent \
|
|
&& mkdir -p /srv/agent-home-stage/.agent /srv/agent-home-stage/.omp/agent \
|
|
&& printf '[install]\nbackend = "copyfile"\n' > /srv/agent-home/.bunfig.toml
|
|
|
|
COPY entrypoint.sh /usr/local/bin/robomp-entrypoint
|
|
RUN chmod +x /usr/local/bin/robomp-entrypoint
|
|
|
|
VOLUME ["/data"]
|
|
EXPOSE 8080
|
|
EXPOSE 8081
|
|
|
|
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/robomp-entrypoint"]
|
|
CMD ["python", "-m", "robomp", "serve"]
|