Skip to content

feat: add CUDA runtime installation helper - #657

Open
binaryaaron wants to merge 9 commits into
binaryaaron/cuda13/runtime-supportfrom
binaryaaron/cuda13/installer
Open

feat: add CUDA runtime installation helper#657
binaryaaron wants to merge 9 commits into
binaryaaron/cuda13/runtime-supportfrom
binaryaaron/cuda13/installer

Conversation

@binaryaaron

@binaryaaron binaryaaron commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a self-contained helper that creates or selects an environment, then installs the requested CPU or CUDA runtime through its Python interpreter.
  • Keep runtime indexes generated from cuda_deps.toml and preserve dry-run behavior without filesystem side effects.
  • Exercise CPU, CUDA 12.9, and CUDA 13.0 through the existing wheel-install container workflow.
  • Restore the repository dprint quality tasks lost during the branch rebase.

Validation

  • mise run test:installer
  • mise run format-check
  • mise run lock-check
  • Wheel build and full wheel-install container target

Final PR in the CUDA 13 stack; depends on #656.

@binaryaaron
binaryaaron requested review from a team as code owners July 16, 2026 18:41
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • main

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7fb0cd3e-0374-4f11-abad-486d6586f59b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch binaryaaron/cuda13/installer

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR completes the CUDA 13 stack by adding install_nss.sh, a bash helper that selects the correct package indexes for cpu, cu129, and cu130 runtimes, and extends tools/gen_cuda_deps.py to generate and keep the script's index arrays in sync with cuda_deps.toml. The cu130 container-build matrix row is also landed, promoting it to full CI coverage.

  • install_nss.sh handles venv creation, driver gating for CUDA 13, dry-run mode, and platform-aware CPU indexes; the generated index block is regenerated by gen_cuda_deps.py --installer and validated by mise run lock-check.
  • Dockerfile.test_ci replaces the inline CPU install commands with install_nss.sh and adds a DRY_RUN=1 cu130 smoke call; ci-checks.yml runs mise run test:installer before the wheel build.
  • E2E bootstrap tasks now honour $NSS_GPU_CUDA_EXTRA (default cu129) so cu130 can be targeted without editing task files.

Confidence Score: 5/5

  • Safe to merge; the new installer and generator changes are well-tested and the CI integration is straightforward.
  • The installer logic is correct and thoroughly exercised by both shell and Python tests. The two observations are style-level: one test dropped a file-integrity assertion for a check=True path that the implementation handles correctly, and the default CONSTRAINTS_URL pointing to main is a new behavior that may warrant a note in the PR but is not a defect in this branch.
  • tests/test_gen_cuda_deps.py lost the assertion that check-mode leaves pyproject.toml unchanged on disk; worth re-adding if you want that invariant explicitly tested.

Important Files Changed

Filename Overview
install_nss.sh New installer script: well-structured, handles CPU/cu129/cu130 runtimes, dry-run mode, venv lifecycle, and CUDA 13 driver gating. Logic is sound; minor behavioral differences from the original Dockerfile inline commands (no explicit --python pin, venv skipped if python exists) are safe in practice.
tools/gen_cuda_deps.py Added installer-fragment generation: build_cuda_installer_fragment, apply_cuda_fragment_to_installer, _update_installer, _installer_index_urls. Pre-validates installer markers before writing pyproject.toml; _update_installer double-reads the file but is harmless. Logic is correct.
tests/tools/test_install_nss.sh Comprehensive bash test harness: dry-run assertions for all three runtimes, help and error paths, a fake-uv integration test verifying venv creation and pip-install invocations, and platform-specific CPU index guard. Well-structured and covers the major installer contracts.
tests/test_gen_cuda_deps.py Adds new installer-fragment tests and updates existing pyproject tests. Drops the assertion that check=True leaves pyproject.toml unmodified on disk — the surviving test for skipping writes only covers the no-drift case, leaving the drift+check invariant implicitly unchecked.
containers/Dockerfile.test_ci CPU install path replaced with install_nss.sh; cu130 added as a DRY_RUN=1 validation. CONSTRAINTS_URL is not overridden, so the installer fetches constraints from main branch at build time — intentional per the script's design but worth noting for PR-branch CI.
.mise/tasks/tests.toml E2E bootstrap tasks now honour $NSS_GPU_CUDA_EXTRA (default cu129), enabling cu130 testing without editing task files. Clean change.
.github/workflows/ci-checks.yml Adds installer dry-run validation step before the wheel build. Correct placement ensures install_nss.sh is exercised in CI.
.github/workflows/container-build.yml cu130 matrix row added — promotes cu130 to full container-build coverage alongside cu129.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[CUDA env var] --> B{main}
    B -->|help / -h / --help| C[usage → exit 0]
    B --> D[runtime_extra]
    D -->|129/cu129/cuda12| E[extra = cu129]
    D -->|130/cu130/cuda13| F[extra = cu130]
    D -->|cpu/CPU| G[extra = cpu]
    D -->|unknown| H[die unsupported]

    E --> I[require_command uv]
    F --> I
    G --> I
    I --> J[resolve_venv_path\nUV_PROJECT_ENVIRONMENT\n→ VIRTUAL_ENV\n→ SCRIPT_DIR/.venv]
    J --> K[build_venv_command\nskip if bin/python exists]
    K --> L{extra == cu130\nDRY_RUN != 1?}
    L -->|yes| M[check_cuda_13_driver\nvia nvidia-smi]
    M -->|driver < 580.65.06| N[die]
    M -->|ok / no nvidia-smi| O[build_install_command]
    L -->|no| O
    O --> P[runtime_indexes\nsets INDEXES array]
    P --> Q[uv pip install\npackage_spec\n-c CONSTRAINTS_URL\n--python VENV_PATH/bin/python\n--index ... × N\n--index-strategy unsafe-best-match]
    Q --> R{DRY_RUN=1?}
    R -->|yes| S[print command only]
    R -->|no| T[execute venv + install]
Loading

Reviews (9): Last reviewed commit: "fix: make runtime installer self-contain..." | Re-trigger Greptile

Comment thread tests/tools/test_install_nss.sh Outdated
Comment thread install_nss.sh
@binaryaaron
binaryaaron force-pushed the binaryaaron/cuda13/runtime-support branch from 4127e30 to 7b0ff2e Compare July 16, 2026 21:52
@binaryaaron
binaryaaron force-pushed the binaryaaron/cuda13/installer branch from 552467d to dceb950 Compare July 16, 2026 21:52
Comment thread install_nss.sh Outdated
@@ -0,0 +1,62 @@
#!/usr/bin/env bash

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

hehe bash test scripts

@binaryaaron
binaryaaron force-pushed the binaryaaron/cuda13/runtime-support branch from 8629058 to 54c2fc2 Compare August 5, 2026 20:13
@binaryaaron
binaryaaron force-pushed the binaryaaron/cuda13/installer branch from 029bd8f to 773a0af Compare August 5, 2026 23:20
andrewwhitecdw pushed a commit to andrewwhitecdw/Safe-Synthesizer that referenced this pull request Aug 13, 2026
…#655)

## Summary

this is one of three stacked prs (NVIDIA-NeMo#656, NVIDIA-NeMo#657) for our overdue
multiple-versions-of-cuda support. This one is the core mechanism for
generating the deps all from one place and handles instructions and docs
for new installation methods.

- Define CPU and CUDA runtime extras, conflicts, package sources, and
indexes in cuda_deps.toml.
- Generate the corresponding marked pyproject.toml sections from that
single source of truth.

## Validation

```
- uv run --offline --script tools/gen_cuda_deps.py cuda_deps.toml --pyproject pyproject.toml --check
- uv lock --check
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary

* **New Features**
* Introduced a tool-managed workflow for CPU/CUDA runtime extras via
`cuda_deps.toml`, with automatic regeneration of dependency lists and
package source/index metadata.
  * Added a `--check`/lock-check flow to prevent CUDA metadata drift.

* **Documentation**
* Updated contributor, agent, README, Docker, and CI guidance to
regenerate from `cuda_deps.toml` and keep the lockfile in sync.

* **Quality & Tests**
* Added end-to-end coverage for generation, splicing, idempotency, and
error cases.

* **Chores / Style**
* Added `dprint`-based TOML formatting and expanded CI formatting
checks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Co-authored-by: Claude <noreply@anthropic.com>
binaryaaron and others added 4 commits August 14, 2026 17:31
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Lands the coverage the previous PR's docs had prematurely claimed:

- Add a cu130 matrix row to container-build.yml so release images are
  actually built and published for both CUDA variants.
- Fix the cu130 GPU e2e lane, which silently re-bootstrapped cu129 via
  .mise/tasks/tests.toml's hardcoded bootstrap-nss call before running,
  so it tested cu129 twice instead of exercising cu130 at all. The e2e
  tasks now bootstrap $NSS_GPU_CUDA_EXTRA (default cu129, unchanged for
  local/other callers), and gpu-tests.yml sets it from the matrix.
- Flip docs, workflow diagram, and skip messages back to accurately
  describe cu130 as enabled now that both are true.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
@binaryaaron
binaryaaron force-pushed the binaryaaron/cuda13/runtime-support branch from 61b0ee9 to 8e96e5c Compare August 14, 2026 18:18
@binaryaaron
binaryaaron force-pushed the binaryaaron/cuda13/installer branch from f2935f1 to 1a850f2 Compare August 14, 2026 18:18
Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
notebooks. Useful for evaluating Safe Synthesizer without a local NVIDIA GPU. The
instance bills continuously and cannot be paused -- delete it when you are finished.

From a source checkout, use the installation helper to select a supported

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion: We don't want the getting started user guide to assume you have a source checkout. Shouldn't we be replacing the uv pip install examples with using a command like curl https://raw.githubusercontent.com/NVIDIA-NeMo/Safe-Synthesizer/refs/heads/main/install.sh | bash or such?

# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: Why is this being removed?

Comment thread install_nss.sh
https://flashinfer.ai/whl/
https://pypi.nvidia.com
)
# <<< END GENERATED CUDA INSTALLER INDEXES - DO NOT EDIT >>>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion: This makes the installer script versioned along with pyproject.toml and the wheel. To successfully install any given version of NSS, you need to get the install_sh.sh script from the tag associated with that version. Can we make this more generic, so it at least doesn't cause a breaking change every time we update vllm? I think @zywind has a setup in brev that pulls the indexes from the wheel? Though there's probably still complications adjusting those for cu129 or 130.

Or if we do need to keep the install script associated with the particular pyproject.toml/uv.lock that exists. Then we sort of can't have the PACKAGE_VERSION env var at all, as other package versions won't generally work. And I'm not sure how this looks for a user installing from the pypi (who doesn't have the repo checked out). Do we create separate install_nss_0_1_11.sh, install_nss_0_1_12.sh, and so on scripts in the repo?

Comment thread README.md
Use `DRY_RUN=1` to print the command before installing. The helper requires
[uv](https://docs.astral.sh/uv/); use the manual commands below only when you
need to customize the installation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion: We'll need some guidance about when to use the install_sh.sh script versus the uv pip install or pip install command I think. And same as the user guide documentation, this README.md is used for pypi so we don't want the installation instructions to assume the user has cloned the repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants