-
Notifications
You must be signed in to change notification settings - Fork 164
feat: add lockfiles for reproducible sandbox builds #1231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,21 @@ | |
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # ============================================================================= | ||
| # Dependency Locking | ||
| # ============================================================================= | ||
| # The sandbox uses pinned dependencies from two lock files: | ||
| # - requirements/sandbox-core.lock (from code_execution.txt — always installed) | ||
| # - requirements/sandbox.lock (from code_execution.txt + stem.txt — skip on CI/arm64) | ||
| # | ||
| # To regenerate after changing code_execution.txt or stem.txt: | ||
| # uv pip compile requirements/code_execution.txt \ | ||
| # --python-version 3.10 -o requirements/sandbox-core.lock | ||
| # uv pip compile requirements/code_execution.txt requirements/stem.txt \ | ||
| # --extra-index-url https://download.pytorch.org/whl/cpu \ | ||
| # --python-version 3.10 -o requirements/sandbox.lock | ||
| # ============================================================================= | ||
|
|
||
| # Use the base image with Python 3.10 and Flask | ||
| FROM tiangolo/uwsgi-nginx-flask:python3.10 | ||
|
|
||
|
|
@@ -59,26 +74,25 @@ RUN cd /lean4/my_project && \ | |
| ENV LEAN_PATH="/lean4/my_project" | ||
| ENV PATH="/lean4/my_project:$PATH" | ||
|
|
||
| # Set up application code and install Python dependencies | ||
| COPY requirements/code_execution.txt /app/requirements.txt | ||
| RUN pip install --no-cache-dir -r /app/requirements.txt | ||
|
|
||
|
|
||
| # Install STEM related libraries | ||
| COPY requirements/stem.txt /app/stem_requirements.txt | ||
|
|
||
|
|
||
| # Speed/size/env hygiene | ||
| ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \ | ||
| UV_SYSTEM_PYTHON=1 \ | ||
| PATH="/root/.local/bin:${PATH}" | ||
|
|
||
| # Install uv | ||
| RUN curl -LsSf https://astral.sh/uv/install.sh | sh | ||
|
Comment on lines
+82
to
+83
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: To pin a specific
[1] For Docker, pin the installer URL the same way (or pin the Docker image tag / digest): ADD https://astral.sh/uv/0.10.0/install.sh /uv-installer.sh[2] If you also need reproducible install behavior (path, no PATH modification, etc.), the installer supports environment variables like 🏁 Script executed: # Look for any version hints in lock files or documentation
fd -type f \( -name "uv.lock" -o -name "uv.toml" -o -name "pyproject.toml" -o -name "requirements*.txt" \) | head -20Repository: NVIDIA-NeMo/Skills Length of output: 232 🏁 Script executed: # Check the Dockerfile context for other version pins or version references
cat -n dockerfiles/Dockerfile.sandbox | head -100Repository: NVIDIA-NeMo/Skills Length of output: 5242 🏁 Script executed: # Look for CI/CD files and setup configurations that may specify uv version
fd -name "*.yml" -o -name "*.yaml" -o -name ".github" | head -20Repository: NVIDIA-NeMo/Skills Length of output: 292 🏁 Script executed: # Search for uv version references in the entire repo
rg "uv.*[0-9]+\.[0-9]+" --max-count 10Repository: NVIDIA-NeMo/Skills Length of output: 523 🏁 Script executed: # Check the lock files themselves for version info
fd -name "*.lock" -type fRepository: NVIDIA-NeMo/Skills Length of output: 292 🏁 Script executed: # Find lock files and CI files
git ls-files | grep -E "(\.lock|\.yml|\.yaml|pyproject\.toml)" | head -30Repository: NVIDIA-NeMo/Skills Length of output: 1318 🏁 Script executed: # Search for uv version references more carefully
rg "uv" --type py --type txt --type toml | grep -i "version\|0\.[0-9]" | head -20Repository: NVIDIA-NeMo/Skills Length of output: 374 🏁 Script executed: # Check if there's a pyproject.toml with uv config
fd "pyproject.toml" -type fRepository: NVIDIA-NeMo/Skills Length of output: 232 🏁 Script executed: # Find lock files more simply
find . -name "*.lock" -type f 2>/dev/null | head -20Repository: NVIDIA-NeMo/Skills Length of output: 122 🏁 Script executed: # Check the GitHub workflow files for uv version pins
cat .github/workflows/tests.yml | head -100Repository: NVIDIA-NeMo/Skills Length of output: 3631 🏁 Script executed: # Look for any mentions of uv version in the codebase
rg "astral.*uv" --max-count 10Repository: NVIDIA-NeMo/Skills Length of output: 464 🏁 Script executed: # Check Dockerfile.nemo-rl to see what UV_VERSION is set to
cat -n dockerfiles/Dockerfile.nemo-rl | grep -A 5 -B 5 "UV_VERSION"Repository: NVIDIA-NeMo/Skills Length of output: 576 🏁 Script executed: # Look for ARG UV_VERSION or ENV UV_VERSION definitions
rg "UV_VERSION" -B 2 -A 2Repository: NVIDIA-NeMo/Skills Length of output: 525 Pin the The whole point of this PR is reproducible sandbox builds, but Dockerfile.nemo-rl correctly pins this with: ARG UV_VERSION=0.9.7
RUN curl -LsSf https://astral.sh/uv/${UV_VERSION}/install.sh | shApply the same pattern to 🤖 Prompt for AI Agents |
||
|
|
||
| # Set up application code directory | ||
| WORKDIR /app | ||
|
|
||
| # Install uv (adds to ~/.local/bin), then install deps | ||
| # Install core Python dependencies from lock file (always) | ||
| COPY requirements/sandbox-core.lock /app/requirements-core.lock | ||
| RUN uv pip install --system -r /app/requirements-core.lock | ||
|
|
||
| # Install full dependencies including STEM libraries (skip on CI/arm64) | ||
| COPY requirements/sandbox.lock /app/requirements.lock | ||
| RUN if [ "$GITHUB_CI" != "1" ] && [ "$TARGETARCH" != "arm64" ]; then \ | ||
| curl -LsSf https://astral.sh/uv/install.sh | sh && \ | ||
| uv pip install --upgrade pip && \ | ||
| uv pip install -r /app/stem_requirements.txt --no-cache-dir --extra-index-url https://download.pytorch.org/whl/cpu; \ | ||
| uv pip install --system -r /app/requirements.lock --extra-index-url https://download.pytorch.org/whl/cpu; \ | ||
| fi | ||
|
|
||
| # For scicode eval - create data directory and download test data | ||
|
|
@@ -132,9 +146,6 @@ RUN gcc -shared -fPIC -o /usr/lib/libblock_network.so /tmp/block_network.c -ldl | |
| COPY dockerfiles/sandbox/start-with-nginx.sh /start-with-nginx.sh | ||
| RUN chmod +x /start-with-nginx.sh | ||
|
|
||
| # Set the working directory to /app | ||
| WORKDIR /app | ||
|
|
||
| # Environment variables for multi-worker setup | ||
| ENV NGINX_PORT=6000 | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # This file was autogenerated by uv via the following command: | ||
| # uv pip compile requirements/code_execution.txt --python-version 3.10 -o requirements/sandbox-core.lock | ||
| annotated-types==0.7.0 | ||
| # via -r requirements/code_execution.txt | ||
| asttokens==3.0.1 | ||
| # via stack-data | ||
| blinker==1.9.0 | ||
| # via flask | ||
| click==8.3.1 | ||
| # via flask | ||
| decorator==5.2.1 | ||
| # via ipython | ||
| exceptiongroup==1.3.1 | ||
| # via ipython | ||
| executing==2.2.1 | ||
| # via stack-data | ||
| flask==3.1.2 | ||
| # via -r requirements/code_execution.txt | ||
| gunicorn==25.0.3 | ||
| # via -r requirements/code_execution.txt | ||
| h5py==3.15.1 | ||
| # via -r requirements/code_execution.txt | ||
| ipython==8.38.0 | ||
| # via -r requirements/code_execution.txt | ||
| itsdangerous==2.2.0 | ||
| # via flask | ||
| jedi==0.19.2 | ||
| # via ipython | ||
| jinja2==3.1.6 | ||
| # via flask | ||
| markupsafe==3.0.3 | ||
| # via | ||
| # flask | ||
| # jinja2 | ||
| # werkzeug | ||
| matplotlib-inline==0.2.1 | ||
| # via ipython | ||
| mpmath==1.3.0 | ||
| # via sympy | ||
| numpy==2.2.6 | ||
| # via | ||
| # -r requirements/code_execution.txt | ||
| # h5py | ||
| # pandas | ||
| # scipy | ||
| packaging==26.0 | ||
| # via gunicorn | ||
| pandas==2.3.3 | ||
| # via -r requirements/code_execution.txt | ||
| parso==0.8.6 | ||
| # via jedi | ||
| pexpect==4.9.0 | ||
| # via ipython | ||
| prompt-toolkit==3.0.52 | ||
| # via ipython | ||
| psutil==7.2.2 | ||
| # via -r requirements/code_execution.txt | ||
| ptyprocess==0.7.0 | ||
| # via pexpect | ||
| pure-eval==0.2.3 | ||
| # via stack-data | ||
| pygments==2.19.2 | ||
| # via ipython | ||
| python-dateutil==2.9.0.post0 | ||
| # via pandas | ||
| pytz==2025.2 | ||
| # via pandas | ||
| scipy==1.15.3 | ||
| # via -r requirements/code_execution.txt | ||
| six==1.17.0 | ||
| # via python-dateutil | ||
| stack-data==0.6.3 | ||
| # via ipython | ||
| sympy==1.14.0 | ||
| # via -r requirements/code_execution.txt | ||
| tqdm==4.67.3 | ||
| # via -r requirements/code_execution.txt | ||
| traitlets==5.14.3 | ||
| # via | ||
| # ipython | ||
| # matplotlib-inline | ||
| typing-extensions==4.15.0 | ||
| # via | ||
| # exceptiongroup | ||
| # ipython | ||
| tzdata==2025.3 | ||
| # via pandas | ||
| wcwidth==0.6.0 | ||
| # via prompt-toolkit | ||
| werkzeug==3.1.5 | ||
| # via flask |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Piping curl to shell (
curl | sh) downloads and executes remote code without verification. Consider downloading the script first, verifying its checksum, then executing it for better security.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!