From 9a84ae7b618fffe8fd0976c965583cac163091ef Mon Sep 17 00:00:00 2001 From: Pepijn Date: Thu, 9 Apr 2026 15:15:43 +0200 Subject: [PATCH] perf(ci): split Dockerfile dep-install from source-copy for faster rebuilds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dep-install layer (uv sync) now only depends on pyproject.toml, uv.lock, and a minimal package stub — not the full src/ tree. Source code changes only rebuild the final COPY layer (seconds, not minutes). Also switch from type=local cache (lost on ephemeral runners) to type=gha (persisted in GitHub Actions cache, shared across all runs). Before: every src/ change → full uv sync rebuild (~8-10 min) After: src/-only change → cached dep layer, ~30s source copy Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/benchmark_tests.yml | 13 +++++++------ docker/Dockerfile.benchmark.libero | 7 +++++-- docker/Dockerfile.benchmark.metaworld | 7 +++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/benchmark_tests.yml b/.github/workflows/benchmark_tests.yml index 9ba8c4b64..c3d274fd3 100644 --- a/.github/workflows/benchmark_tests.yml +++ b/.github/workflows/benchmark_tests.yml @@ -83,8 +83,9 @@ jobs: with: cache-binary: false - # Build the benchmark-specific image; layer cache lives in the runner's - # local Docker daemon — reused across re-runs on the same machine. + # Build the benchmark-specific image. Layer cache uses GHA cache (persists + # across runners). The Dockerfile separates dep-install from source-copy, + # so code-only changes skip the slow uv-sync layer entirely. - name: Build Libero benchmark image uses: docker/build-push-action@v6 # zizmor: ignore[unpinned-uses] with: @@ -93,8 +94,8 @@ jobs: push: false load: true tags: lerobot-benchmark-libero:ci - cache-from: type=local,src=/tmp/.buildx-cache-libero - cache-to: type=local,dest=/tmp/.buildx-cache-libero,mode=max + cache-from: type=gha,scope=benchmark-libero + cache-to: type=gha,scope=benchmark-libero,mode=max - name: Login to Hugging Face if: env.HF_USER_TOKEN != '' @@ -247,8 +248,8 @@ jobs: push: false load: true tags: lerobot-benchmark-metaworld:ci - cache-from: type=local,src=/tmp/.buildx-cache-metaworld - cache-to: type=local,dest=/tmp/.buildx-cache-metaworld,mode=max + cache-from: type=gha,scope=benchmark-metaworld + cache-to: type=gha,scope=benchmark-metaworld,mode=max - name: Run MetaWorld smoke eval (1 episode) run: | diff --git a/docker/Dockerfile.benchmark.libero b/docker/Dockerfile.benchmark.libero index b3f7e69db..878f8b473 100644 --- a/docker/Dockerfile.benchmark.libero +++ b/docker/Dockerfile.benchmark.libero @@ -61,9 +61,11 @@ ENV HOME=/home/user_lerobot \ RUN uv venv --python python${PYTHON_VERSION} -# Install only lerobot[libero] — completely isolated from metaworld's dep tree +# ── Dependency layer (cached unless pyproject.toml / uv.lock change) ──────── +# Copy only the files uv needs to resolve deps, plus a minimal package stub +# so the editable install can succeed without the full source tree. COPY --chown=user_lerobot:user_lerobot setup.py pyproject.toml uv.lock README.md MANIFEST.in ./ -COPY --chown=user_lerobot:user_lerobot src/ src/ +RUN mkdir -p src/lerobot && touch src/lerobot/__init__.py src/lerobot/py.typed RUN uv sync --locked --extra libero --extra smolvla --no-cache @@ -84,6 +86,7 @@ snapshot_download(repo_id='lerobot/libero-assets', repo_type='dataset', \ RUN chmod +x /lerobot/.venv/lib/python${PYTHON_VERSION}/site-packages/triton/backends/nvidia/bin/ptxas +# ── Source layer (rebuilds in seconds on code-only changes) ───────────────── COPY --chown=user_lerobot:user_lerobot . . CMD ["/bin/bash"] diff --git a/docker/Dockerfile.benchmark.metaworld b/docker/Dockerfile.benchmark.metaworld index 0c916c553..0f4d8a988 100644 --- a/docker/Dockerfile.benchmark.metaworld +++ b/docker/Dockerfile.benchmark.metaworld @@ -61,14 +61,17 @@ ENV HOME=/home/user_lerobot \ RUN uv venv --python python${PYTHON_VERSION} -# Install only lerobot[metaworld] — completely isolated from libero's dep tree +# ── Dependency layer (cached unless pyproject.toml / uv.lock change) ──────── +# Copy only the files uv needs to resolve deps, plus a minimal package stub +# so the editable install can succeed without the full source tree. COPY --chown=user_lerobot:user_lerobot setup.py pyproject.toml uv.lock README.md MANIFEST.in ./ -COPY --chown=user_lerobot:user_lerobot src/ src/ +RUN mkdir -p src/lerobot && touch src/lerobot/__init__.py src/lerobot/py.typed RUN uv sync --locked --extra metaworld --extra smolvla --no-cache RUN chmod +x /lerobot/.venv/lib/python${PYTHON_VERSION}/site-packages/triton/backends/nvidia/bin/ptxas +# ── Source layer (rebuilds in seconds on code-only changes) ───────────────── COPY --chown=user_lerobot:user_lerobot . . CMD ["/bin/bash"]