Skip to content

Reworks modular installation and add tests and updates docs#5650

Merged
kellyguo11 merged 21 commits into
isaac-sim:developfrom
kellyguo11:fix-modular-install
May 17, 2026
Merged

Reworks modular installation and add tests and updates docs#5650
kellyguo11 merged 21 commits into
isaac-sim:developfrom
kellyguo11:fix-modular-install

Conversation

@kellyguo11
Copy link
Copy Markdown
Contributor

@kellyguo11 kellyguo11 commented May 16, 2026

Description

Refactors the IsaacLab installation model to simplify the user experience, adds
comprehensive installation CI tests (including conda).


Motivation

The previous installation model required users to name every individual submodule
(./isaaclab.sh -i assets,tasks,physx,contrib,newton,rl[rsl-rl]), exposing internal
implementation details. Users shouldn't need to know that tasks depends on physx
or that contrib exists — they just want to train with Newton or run with Isaac Sim.


Changes

1. Installation model refactor

source/isaaclab/isaaclab/cli/commands/install.py

  • Replaced VALID_ISAACLAB_SUBMODULES / VALID_RL_FRAMEWORKS with three typed
    constants that make the tier structure explicit:
    • CORE_ISAACLAB_SUBMODULES: list[str] — always installed (isaaclab, assets,
      contrib, experimental, newton, ov, ovphysx, physx, rl, tasks, tasks_experimental,
      visualizers)
    • OPTIONAL_ISAACLAB_SUBMODULES: dict[str, str] — opt-in heavy submodules
      (mimic, teleop)
    • VALID_EXTRA_FEATURES: set[str] — opt-in heavy dependency groups
      (contrib, newton, ov, rl, visualizer)
  • Rewrote command_install(install_type) to always install all core submodules,
    then layer optional submodules and extra feature dependencies on top.
  • Added _install_extra_feature(feature_name, selector) replacing
    _install_extra_frameworks.
  • ./isaaclab.sh -i (no args) or -i all installs everything including mimic
    and teleop.
  • ./isaaclab.sh -i none installs all core submodules with no optional extras.
  • Unknown tokens (e.g. old tasks, assets) emit a [WARNING] and are skipped
    gracefully.

source/isaaclab/isaaclab/cli/__init__.py

  • Rewrote the -i help text to document the three-tier model with examples.

source/isaaclab/setup.py

  • Simplified EXTRAS_REQUIRE to isaacsim and all only.

source/isaaclab_mimic/setup.py

  • Removed the empty robomimic extra.

pyproject.toml (root)

  • [project.dependencies]: lists all core submodules (bare, no extras).
  • [project.optional-dependencies]: simplified to isaacsim and all.

2. Documentation

docs/source/setup/installation/include/src_build_isaaclab.rst

  • Rewrote the install section: new tables for optional submodules and extra feature
    sets with their selectors; updated all example commands.

docs/source/setup/installation/kitless_installation.rst

  • Updated the selective-install table and examples to match the new model.

3. Installation CI tests

New and updated test files

File Status What it tests
test_install_command_parsing.py New Unit tests for _split_install_items, constant consistency, and command_install dispatch logic (all mocked, no pip)
test_isaaclabx_i_none.py New ./isaaclab.sh -i none installs all core submodules; optional submodules absent
test_isaaclabx_i_rl.py New rl[rsl-rl], rl[skrl], rl[sb3] each install the right framework; rl (no selector) installs all
test_isaaclabx_i_mimic.py New mimic is importable after -i mimic; absent after -i none
test_isaaclabx_i_visualizer.py New visualizer[rerun], visualizer[viser], visualizer (all) install the right backends
test_install_workflow_training.py New E2E uv × conda training workflows (see table below)
test_isaaclabx_i_physx.py Updated Reflects physx in core set (no longer requires -i physx)
test_isaaclabx_uv_smoke.py Updated assets / tasks are always-installed core; newton is an extra
test_isaaclabx_uv_training.py Updated Install command updated from old token list to newton,rl[all]

test_install_workflow_training.py — E2E matrix

Test Install command Marker
test_uv_none_installs_core_submodules -i none @uv
test_uv_newton_rsl_rl_trains_cartpole -i newton,rl[rsl-rl] @uv
test_uv_newton_ov_rsl_rl_trains_cartpole -i newton,ov,rl[rsl-rl] @uv
test_uv_all_trains_cartpole -i all @uv
test_conda_none_installs_core_submodules -i none (conda env) @conda
test_conda_newton_rsl_rl_trains_cartpole -i newton,rl[rsl-rl] (conda env) @conda

source/isaaclab/test/install_ci/utils.py

  • Added drop_keys(env, keys) helper for stripping venv/conda activation markers
    before creating isolated environments.
  • Added Conda_Mixin with create_conda_env(), destroy_conda_env(), and
    run_in_conda_env() for conda-based test classes.

source/isaaclab/test/install_ci/conftest.py

  • Registered conda and timeout as known pytest markers.

4. Conda CI infrastructure

docker/Dockerfile.installci-conda (new)

  • Layers Miniconda on top of the existing uv-based Dockerfile.installci image.
  • Used by the new install-tests-conda CI job.

tools/run_install_ci.py

  • Refactored build logic into _build_image() helper.
  • Added --conda flag: builds the uv base image first, then the conda layer on
    top; routes to the conda image for the Docker run.

.github/workflows/install-ci.yml

  • Renamed existing job to Installation Tests (uv); added -m uv so it only runs
    uv-marked tests.
  • Added Installation Tests (conda) job with --conda and -m conda,
    timeout-minutes: 150 (extra headroom for two-stage Docker build).
  • Fixed SIGPIPE in render_table / any_match shell functions: replaced
    printf '%s\n' "$files" | grep with grep <<< "$files" to avoid broken-pipe
    signals when grep exits early with -m or -q.

Testing

  • test_install_command_parsing.py: 41 unit tests, all pass without GPU or network.
  • Install + training verified end-to-end on this machine:
    • ./isaaclab.sh -i newton,ov,rl[rsl_rl] → clean install, no warnings
    • ./isaaclab.sh train --rl_library rsl_rl --task Isaac-Cartpole-Direct-v0 --num_envs=16 --max_iterations=10 "presets=newton" --headless → 10 iterations, exit 0, ~2900 steps/sec

Migration guide

Old command New command
./isaaclab.sh -i assets,tasks,physx,contrib ./isaaclab.sh -i none (all core always installed)
./isaaclab.sh -i assets,tasks,ov,rl[rsl-rl] ./isaaclab.sh -i ov,rl[rsl-rl]
./isaaclab.sh -i newton,rl[all] unchanged
./isaaclab.sh -i mimic,teleop unchanged
uv pip install isaaclab[tasks,rl,assets] uv pip install isaaclab[all]

@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation isaac-mimic Related to Isaac Mimic team infrastructure labels May 16, 2026
@kellyguo11 kellyguo11 marked this pull request as draft May 16, 2026 06:47
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 16, 2026

Greptile Summary

This PR refactors the IsaacLab installation model from an explicit submodule enumeration (requiring users to know internal dependency chains) to a tiered system of core submodules always installed, optional heavy submodules, and named extra-feature sets with optional selectors. It adds conda CI infrastructure and a comprehensive suite of unit and integration tests covering the new install paths.

  • Install model: CORE_ISAACLAB_SUBMODULES is always installed; OPTIONAL_ISAACLAB_SUBMODULES (mimic, teleop) and VALID_EXTRA_FEATURES (contrib, newton, ov, rl, visualizer) are opt-in. ./isaaclab.sh -i and -i all install core + optional submodules + auto extra features (newton, rl, visualizer); -i none installs core only.
  • CI infrastructure: Two new Docker-based CI jobs (uv and conda marked) with isolated environment creation/teardown, JUnit XML result extraction via docker cp after container exit, and UUID-tagged container names to avoid collisions.
  • Test coverage: 41 unit tests in test_install_command_parsing.py mock all I/O and cover all/none/token/malformed-token paths; integration tests in new files cover RL frameworks, visualizer backends, mimic, physx, and E2E conda training workflows.

Confidence Score: 5/5

The installation refactor is well-scoped, all I/O paths are unit-tested with mocks, and E2E integration tests cover the major install combinations.

The install dispatch logic is correct, the bracket-depth parser handles nested commas properly, and the conda mixin cleanup is guarded with hasattr checks. All findings are style or UX polish with no functional correctness issues.

source/isaaclab/isaaclab/cli/commands/install.py — the newton/visualizer auto-extra overlap and the contrib no-selector messaging are minor but worth a second look.

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/cli/commands/install.py Core install logic rewritten: tiered constants (CORE/OPTIONAL/VALID_EXTRA_FEATURES), new _install_extra_feature dispatcher replacing _install_extra_frameworks, malformed-token warning added. Minor: double install of isaaclab_visualizers in -i all (newton + visualizer auto-extras), and silent print_info for explicit -i contrib with no selector.
source/isaaclab/test/install_ci/test_install_command_parsing.py 41 unit tests covering _split_install_items, constant sanity checks, and full command_install dispatch for all/none/tokens/malformed tokens — all I/O mocked. Comprehensive and well-structured.
tools/run_install_ci.py Refactored to _build_image helper, added --conda flag for layered conda Docker build, switched from bind-mount to docker cp for JUnit XML extraction, added UUID-tagged container names for safe concurrent runs, and corrected cache paths from /root to /home/isaaclab for non-root user.
source/isaaclab/test/install_ci/utils.py Adds drop_keys() helper and Conda_Mixin with create/destroy/run helpers for isolated conda environments. Minor: docstring references non-existent class name UVMixin instead of UV_Mixin.
source/isaaclab/test/install_ci/Dockerfile.installci-conda New Dockerfile that layers Miniconda onto the uv base image, installs into the non-root isaaclab user's home directory, and accepts conda ToS non-interactively. Correct USER directive flow (root for install, isaaclab for runtime).
.github/workflows/install-ci.yml Splits the single install-tests job into uv and conda variants with -m uv/-m conda marker filters; adds conda job with 150-minute timeout; fixes SIGPIPE in shell functions by using herestring instead of pipe to grep.
docker/test/test_dockerfile_nonroot.py Widens Dockerfile search from docker/ only to entire repo tree; adds _find_dockerfile helper that asserts uniqueness; updates DOCKERFILE_RUNTIME_USERS to expect isaaclab user for installci.
source/isaaclab/test/install_ci/test_install_workflow_training.py New E2E training workflow tests for uv and conda environments; covers -i none, -i newton,rl[rsl-rl], -i newton,ov,rl[rsl-rl], and -i all; try/finally ensures env cleanup on failure.
pyproject.toml Simplified optional-dependencies from many granular extras to just isaacsim and all; core dependencies now list all submodules without extras.

Reviews (2): Last reviewed commit: "install contrib by default" | Re-trigger Greptile

Comment on lines 757 to +760
if "[" in token:
bracket_pos = token.index("[")
name = token[:bracket_pos].strip()
editable = token[bracket_pos:].strip()
selector = token[bracket_pos + 1 : token.index("]")].strip()
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.

P1 Unhandled ValueError for malformed bracket tokens

token.index("]") raises ValueError when a token contains [ but no closing ] (e.g., the user types rl[rsl-rl by accident). The old code used token[bracket_pos:] and never called .index("]"), so it was immune to this. The install command will crash with an unhandled exception instead of emitting a warning and continuing. The new test file has no test covering this case.

Comment on lines +542 to +544
if feature_name == "newton":
print_info("Installing newton extras (newton[sim], PyOpenGL-accelerate, imgui-bundle)...")
run_command(pip_cmd + ["install", "--editable", f"{source_dir}/isaaclab_newton[all]"])
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.

P2 The selector parameter is silently ignored for the newton feature. If a user passes newton[sim] or any other selector, it is discarded without warning, which can be confusing since every other feature respects its selector. A warning makes the contract explicit.

Suggested change
if feature_name == "newton":
print_info("Installing newton extras (newton[sim], PyOpenGL-accelerate, imgui-bundle)...")
run_command(pip_cmd + ["install", "--editable", f"{source_dir}/isaaclab_newton[all]"])
if feature_name == "newton":
if selector:
print_warning(
f"'newton' does not support selectors (got '{selector}'). "
"Installing all newton extras."
)
print_info("Installing newton extras (newton[sim], PyOpenGL-accelerate, imgui-bundle)...")
run_command(pip_cmd + ["install", "--editable", f"{source_dir}/isaaclab_newton[all]"])

" Install optional heavy dependencies for a feature on top of the core.\n"
" Supports an optional selector in brackets:\n"
" rl[rsl-rl|skrl|sb3|rl-games] (default: all)\n"
" visualizer[newton|rerun|viser] (default: all)\n"
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.

P2 The help text lists only newton|rerun|viser as visualizer selectors, but the docs table in both RST files (and the isaaclab_visualizers extras) also include kit. Omitting it here leaves users unaware of the kit backend.

Suggested change
" visualizer[newton|rerun|viser] (default: all)\n"
" visualizer[kit|newton|rerun|viser] (default: all)\n"

Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

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

🔬 Code Review: Modular Installation Rework

Overview

This PR introduces a significant architectural improvement to Isaac Lab's installation system, moving from a submodule-centric model to a cleaner core+extras approach. The design is sound and well-documented.


🔴 Critical: CI Test Collection Failure

File: source/isaaclab/test/install_ci/test_install_command_parsing.py:28

The Installation Tests CI job fails during test collection:

ModuleNotFoundError: No module named 'isaaclab'

Root Cause: The test file attempts to import from isaaclab.cli.commands.install before the package is installed in the CI environment. Line 26-27 adds the source path to sys.path:

_ISAACLAB_SRC = Path(__file__).resolve().parents[4] / "isaaclab"
if str(_ISAACLAB_SRC) not in sys.path:
    sys.path.insert(0, str(_ISAACLAB_SRC))

However, from test_install_command_parsing.py, parents[4] resolves to the repository root, but the target should be source/isaaclab/isaaclab (the actual Python package directory), not source/isaaclab.

Fix: Change line 26 to:

_ISAACLAB_SRC = Path(__file__).resolve().parents[3]  # source/isaaclab

Or more explicitly:

_ISAACLAB_SRC = Path(__file__).resolve().parents[4] / "source" / "isaaclab"

🟡 Warnings

1. CHANGELOG.rst Entry Missing

Per CONTRIBUTING.md, user-facing changes require a changelog entry. This PR significantly changes the CLI interface for --install and should be documented.

2. Documentation: Inconsistent Framework Name Separator

The docs use both rsl-rl (hyphen) and show examples, but the old code used rsl_rl (underscore). While the new code handles both, the docs should clarify if both are valid or if one is deprecated.


Update (da8f581): Empty commit to retrigger CI — no code changes. Previous review comments still apply.


Update (887bf19): Improves Docker bind-mount permission handling in tools/run_install_ci.py. The change iterates over existing files in the results directory and sets their permissions to 0o666, preventing PermissionError when stale files owned by root exist from previous CI runs. This is a good defensive fix for CI reliability. ✅ No concerns with this change.


Update (82d505e): Significant improvement to JUnit XML results handling in tools/run_install_ci.py. Instead of bind-mounting the results directory (which caused permission issues), the script now:

  1. Creates a named container (using uuid for uniqueness) instead of using --rm
  2. Writes pytest results to a container-internal path (/tmp/isaaclab-installci-results.xml)
  3. Copies results out using docker cp after the container exits
  4. Properly cleans up with docker rm -f in a finally block
  5. Handles timeout gracefully by killing the named container

This is an excellent architectural change that completely avoids the root-owned-file permission issues inherent in bind-mount approaches. The implementation includes proper error handling and warnings. ✅ Well done!


Update (47679f3): Major refinement of the optional submodule/extra feature model:

Changes:

  • contrib and ov are now optional submodules (not extra features)
  • ov maps to two packages: isaaclab_ov + isaaclab_ovphysx
  • Removed isaaclab_contrib, isaaclab_ov, isaaclab_ovphysx from core submodules
  • New _install_optional_submodule_extra_dependencies() handles dependency extras:
    • contrib[rlinf] for rlinf dependencies
    • ov[ovrtx|ovphysx|all] for OV runtime wheels
  • Updated docs with clear examples for new selector syntax
  • Test preset changed from presets=newtonpresets=newton_mjwarp
  • Comprehensive test coverage added for the new model

Assessment:
✅ The architectural separation is cleaner — core packages are truly lightweight, while heavy dependencies require explicit opt-in via selectors. This matches the stated goal of making base installation faster.

✅ The _install_optional_submodule_extra_dependencies() implementation properly validates selectors and handles the all convenience selector for ov.

⚠️ Minor concern: The MANUAL_EXTRA_FEATURES set is now empty (set()). If this is intentional and there are no longer features excluded from all, the constant might be removed for clarity (or documented as a placeholder for future use).

Overall, this commit significantly improves the installation model. The CI test collection issue from the original review may still need addressing.


Update (e2d8a46): Excellent refinement! This commit addresses the previous concern about MANUAL_EXTRA_FEATURES being empty.

Key architectural change: isaaclab_ov and isaaclab_ovphysx are now core submodules (always installed). This allows task configs to import OV preset classes without requiring the heavy OV runtime wheels.

What changed:

  • ov moved from OPTIONAL_ISAACLAB_SUBMODULES to VALID_EXTRA_FEATURES
  • MANUAL_EXTRA_FEATURES = {"ov"} — OV runtime deps excluded from -i all (addresses previous concern ✅)
  • New dedicated _install_ov_extra_dependencies() function for cleaner code separation
  • Docs clarified: OV source packages are core; use ov[ovrtx|ovphysx|all] for runtime wheels
  • Tests updated to verify new behavior

Assessment: ✅ This is a well-thought-out design decision. Users get the OV abstractions/presets out of the box, but the heavy runtime wheels (~GB) remain opt-in. The code is cleaner with the dedicated OV handler, and the test coverage properly validates the new model.

No new concerns with this commit.


Update (4b653b4): Moves isaaclab_contrib from optional submodule back to core. This is the right call — other core packages (like isaaclab_tasks) may import contrib utilities, so it shouldn't require explicit opt-in. The heavy runtime deps (rlinf) still require contrib[rlinf] selector. contrib is now an extra feature (like ov) — source always installed, heavy deps opt-in.

Final architecture after all commits:

Tier Packages When installed
Core (always) isaaclab, assets, contrib, experimental, newton, ov, ovphysx, physx, rl, tasks, tasks_experimental, visualizers Every -i invocation
Optional submodules mimic, teleop -i all or explicit token
Extra features (auto) newton, rl, visualizer -i all (default)
Extra features (manual) contrib[rlinf], ov[ovrtx/ovphysx] Explicit selector only

Verdict: Ready to merge. ✅ All CI green (39 checks). The installation model is clean, well-tested, and has converged on a sensible design. No remaining concerns.

@kellyguo11 kellyguo11 marked this pull request as ready for review May 17, 2026 04:03
@kellyguo11 kellyguo11 merged commit 2ace55b into isaac-sim:develop May 17, 2026
64 of 65 checks passed
kellyguo11 added a commit that referenced this pull request May 18, 2026
# Description

Fixes the uv run path that got broken by #5650. Updates the available
options to align closer with the new logic for ./isaaclab.sh -i modular
installation.

Also adds more unit tests for uv run and pip package.

## Type of change

<!-- As you go through the list, delete the ones that are not
applicable. -->

- Bug fix (non-breaking change which fixes an issue)

## Checklist

- [x] I have read and understood the [contribution
guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html)
- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [ ] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

<!--
As you go through the checklist above, you can mark something as done by
putting an x character in it

For example,
- [x] I have done this task
- [ ] I have not done this task
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation infrastructure isaac-mimic Related to Isaac Mimic team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant