Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions .github/wheel-constraints/nemo-platform-plugin.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
# Partial dependency constraints for the CI wheel install-smoke-test.
# Pins the DIRECT external deps of the built nemo-platform-plugin wheel to vetted versions for
# reproducibility; deep transitives resolve normally and cannot self-conflict.
# reproducibility; deep transitives resolve normally (so they stay py3.14-compatible and
# cannot self-conflict). litellm is capped <1.92 — its 1.92.0 native build has no py3.14 wheel.
# Regenerate with: script/compile-wheel-constraints.sh <dir-with-built-wheels>
#
anthropic==0.118.0
anthropic==0.120.2
anyio==4.14.2
distro==1.9.0
docker==7.2.0
fastapi==0.139.2
fsspec==2026.6.0
fastapi==0.141.1
fsspec==2026.7.0
httpx==0.28.1
jsonschema==4.26.0
lark==1.3.1
ngcsdk==4.21.0
ngcsdk==4.34.7
nvidia-ml-py==13.610.43
openai==2.47.0
prompt-toolkit==3.0.52
openai==2.52.0
prompt-toolkit==3.0.53
psutil==7.2.2
pydantic-settings==2.14.2
pydantic==2.13.4
Expand All @@ -25,3 +26,4 @@ rich==15.0.0
sniffio==1.3.1
typer==0.25.1
typing-extensions==4.16.0
litellm<1.92 # 1.92.0 native build has no py3.14 wheel
29 changes: 16 additions & 13 deletions .github/wheel-constraints/nemo-platform-services.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# Partial dependency constraints for the CI wheel install-smoke-test.
# Pins the DIRECT external deps of the built nemo-platform[services] wheel to vetted versions for
# reproducibility; deep transitives resolve normally and cannot self-conflict.
# reproducibility; deep transitives resolve normally (so they stay py3.14-compatible and
# cannot self-conflict). litellm is capped <1.92 — its 1.92.0 native build has no py3.14 wheel.
# Regenerate with: script/compile-wheel-constraints.sh <dir-with-built-wheels>
#
aioboto3==15.5.0
aiofiles==25.1.0
aiohttp==3.14.3
aiosqlite==0.22.1
alembic==1.18.5
anthropic==0.118.0
anthropic==0.120.2
anyio==4.14.2
asyncpg==0.31.0
base58==2.1.1
Expand All @@ -21,36 +22,37 @@ datasets==4.3.0
distro==1.9.0
docker==7.2.0
duckdb==1.5.5
fastapi==0.139.2
fastmcp==3.4.4
fastapi==0.141.1
fastmcp==3.4.5
fsspec==2025.9.0
greenlet==3.5.4
gunicorn==26.0.0
httpx==0.28.1
huggingface-hub==1.24.0
huggingface-hub==1.26.0
hvac==2.4.0
jinja2==3.1.6
jsonpath-ng==1.8.0
jsonschema==4.26.0
kubernetes==36.0.3
langchain-aws==1.1.0
langchain-community==0.3.31
langchain-core==1.5.0
langchain-core==1.5.3
langchain-nvidia-ai-endpoints==1.4.3
langchain-openai==1.4.0
langchain-openai==1.4.1
langchain==1.3.14
lark==1.3.1
nemo-anonymizer==0.3.1
nemo-fabric-adapters-hermes==0.1.0
nemo-fabric==0.1.0
nemo-relay==0.6.0
nemo-safe-synthesizer==0.1.7
nemoguardrails==0.23.0
ngcsdk==4.21.0
ngcsdk==4.34.7
nvidia-ml-py==13.610.43
nvidia-nat-config-optimizer==1.8.0
nvidia-nat-core==1.8.0
nvidia-nat-langchain==1.8.0
openai==2.47.0
openai==2.52.0
opentelemetry-distro==0.64b0
opentelemetry-exporter-otlp-proto-grpc==1.43.0
opentelemetry-exporter-otlp-proto-http==1.43.0
Expand All @@ -65,9 +67,9 @@ opentelemetry-processor-baggage==0.65b0
opentelemetry-proto==1.43.0
opentelemetry-sdk==1.43.0
pandas==2.3.3
prometheus-client==0.25.0
prometheus-fastapi-instrumentator==8.0.2
prompt-toolkit==3.0.52
prometheus-client==0.26.0
prometheus-fastapi-instrumentator==8.1.0
prompt-toolkit==3.0.53
psutil==7.2.2
psycopg2-binary==2.9.12
pyarrow==24.0.0
Expand All @@ -92,7 +94,8 @@ typer==0.25.1
types-aioboto3==15.5.0
typing-extensions==4.16.0
urllib3==2.7.0
uvicorn==0.51.0
uvicorn==0.52.0
wasmtime==47.0.1
xdg-base-dirs==6.0.2
yara-python==4.5.1
litellm<1.92 # 1.92.0 native build has no py3.14 wheel
37 changes: 37 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,42 @@ jobs:
retention-days: 7
if-no-files-found: error

wheel-constraints-lint:
name: Wheel constraints lint
needs: [wheel-build]
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
with:
python-version: "3.12"
enable-cache: true
cache-dependency-glob: uv.lock
- name: Download nemo-platform wheel
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: nemo-platform-wheel-py3.12
path: ${{ runner.temp }}/wheel-constraints/nemo-platform-wheel-py3.12
- name: Download nemo-platform-plugin wheel
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: nemo-platform-plugin-wheel-py3.12
path: ${{ runner.temp }}/wheel-constraints/nemo-platform-plugin-wheel-py3.12
- name: Check generated wheel constraints
shell: bash
run: |
set -euo pipefail
bash -n script/compile-wheel-constraints.sh
script/compile-wheel-constraints.sh "${RUNNER_TEMP}/wheel-constraints"
git diff --exit-code
Comment on lines +1249 to +1250

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
rg -n -C 3 'uv pip install|--constraint|--index|--find-links|--offline|uv\.lock' \
  script/compile-wheel-constraints.sh

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 1180


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- compile script ---'
cat -n script/compile-wheel-constraints.sh | sed -n '1,180p'

printf '%s\n' '--- workflow context ---'
cat -n .github/workflows/ci.yaml | sed -n '1225,1260p;1960,1985p'

printf '%s\n' '--- resolver and generated-file references ---'
rg -n -C 3 'compile-wheel-constraints|wheel-constraints|LITELLM_CAP|constraints' \
  .github/workflows/ci.yaml script .gitignore pyproject.toml uv.lock 2>/dev/null || true

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 18398


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

script = Path("script/compile-wheel-constraints.sh").read_text()
install = re.search(
    r"^\s*uv pip install .*$",
    script,
    re.MULTILINE,
)
if not install:
    raise SystemExit("uv pip install command not found")

command = install.group(0)
flags = {
    name: bool(re.search(pattern, command))
    for name, pattern in {
        "--offline": r"\B--offline\b",
        "--index": r"\B--index(?:-url)?\b",
        "--find-links": r"\B--find-links\b",
        "--require-hashes": r"\B--require-hashes\b",
        "--constraint": r"\B--constraint\b",
    }.items()
}
print("resolver command:", command)
print("resolver flags:", flags)
print("uses uv.lock:", bool(re.search(r"\buv\.lock\b", script)))
print("uses mutable package spec:", bool(re.search(r'"[^"]*\[[^"]*\]"', command)))
PY

printf '%s\n' '--- tracked generated constraints ---'
git ls-files .github/wheel-constraints
for file in $(git ls-files .github/wheel-constraints); do
  printf '%s\n' "--- ${file} ---"
  sed -n '1,24p' "$file"
done

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 2196


Make wheel-constraint generation deterministic.

uv pip install uses a mutable package index and only constrains litellm. A new compatible release can change .github/wheel-constraints/*.txt, causing git diff --exit-code to fail wheel-constraints-lint on unrelated changes. Use an immutable index snapshot or another deterministic resolver input before relying on this required gate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yaml around lines 1249 - 1250, Update the
wheel-constraint generation flow around script/compile-wheel-constraints.sh so
uv pip install resolves against an immutable package-index snapshot or
equivalent deterministic resolver input, while constraining all required
dependencies rather than only litellm. Preserve the existing git diff
--exit-code validation and ensure repeated runs produce identical
.github/wheel-constraints/*.txt output.


# Test each wheel: install from the artifact and run basic CLI /
# import checks.
wheel-test:
Expand Down Expand Up @@ -1938,6 +1974,7 @@ jobs:
# - python-integration-test
- require-nvskills
- wheel-build
- wheel-constraints-lint
- wheel-test
- python-e2e-test
- web-typecheck
Expand Down
8 changes: 4 additions & 4 deletions script/compile-wheel-constraints.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
# script/compile-wheel-constraints.sh <dir-with-both-wheels>
#
# Wheels come from `uv build --package nemo-platform[-plugin]` (nemo-platform
# needs the Studio/node toolchain) or a CI "<pkg>-wheel-py3.11" artifact
# (`gh run download <run-id> -n nemo-platform-wheel-py3.11 -D <dir>`).
# needs the Studio/node toolchain) or a CI "<pkg>-wheel-py3.12" artifact
# (`gh run download <run-id> -n nemo-platform-wheel-py3.12 -D <dir>`).
set -euo pipefail

WHEEL_DIR="${1:?usage: script/compile-wheel-constraints.sh <dir-with-built-wheels>}"
Expand All @@ -35,7 +35,7 @@ emit_constraints() {
local wheel="$1" spec="$2" label="$3" out="$4" venv meta
venv="$(mktemp -d)"
meta="$(mktemp -d)"
uv venv "${venv}" --python 3.11 --quiet
uv venv "${venv}" --python 3.12 --quiet
# Resolve+install once with the cap so we snapshot consistent, py3.14-safe versions.
printf '%s\n' "${LITELLM_CAP%% *}" >"${meta}/cap.txt"
uv pip install --python "${venv}/bin/python" --constraint "${meta}/cap.txt" "${spec}" >/dev/null
Expand All @@ -61,7 +61,7 @@ PY
printf '# Regenerate with: script/compile-wheel-constraints.sh <dir-with-built-wheels>\n#\n'
while read -r name; do
[[ -n "${name}" ]] || continue
ver="$("${venv}/bin/python" -c "import importlib.metadata as m; print(m.version('${name}'))" 2>/dev/null || true)
ver="$("${venv}/bin/python" -c "import importlib.metadata as m; print(m.version('${name}'))" 2>/dev/null || true)"
[[ -n "${ver}" ]] && printf '%s==%s\n' "${name}" "${ver}"
done <"${meta}/names.txt" | sort
printf '%s\n' "${LITELLM_CAP}"
Expand Down
Loading