[Workflow] Fix template generator in uv environments - #7480
Conversation
Greptile SummaryThe PR removes runtime package installation from the project-template launcher and makes its dependencies available through package metadata.
Confidence Score: 5/5The PR appears safe to merge, with no concrete changed-code failure established. The supported uv and wheel paths install the prompt and rendering dependencies through package metadata, and the new prompt implementation preserves validation and retry behavior for the reviewed input paths. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
Install[Install Isaac Lab] --> Metadata[Package metadata installs Rich and Jinja2]
Metadata --> Command[Run isaaclab --new]
Command --> Generator[Launch template generator directly]
Generator --> Prompts[Rich interactive prompts]
Prompts --> Render[Jinja2 renders project templates]
Reviews (1): Last reviewed commit: "Fix template generator in uv environment..." | Re-trigger Greptile |
There was a problem hiding this comment.
Isaac Lab Review Bot
Reviewed the removal of runtime pip installation from isaaclab --new, the migration of template dependencies into root and wheel metadata, and the replacement of InquirerPy prompts with Rich-based input. The changed paths are internally consistent, with regression coverage for command dispatch, prompt validation, and generated wheel dependencies.
- Design and architecture: Dependency ownership now resides in installation metadata rather than runtime environment mutation. The removed
tools/template/requirements.txtwas tied to the deleted pip-install path, while Jinja2 and the existing Rich dependency are available through source and generated wheel metadata. - API: The prompt helper signatures and return types remain compatible, while
CLIHandler.__init__adds an optional console parameter. Selection tokens and separator handling used by the generator remain represented. A residual compatibility consideration is reliance on Rich's case-insensitive choice normalization, but the patch provides no concrete breakage path. - Implementation: The implementation validates text and path inputs through re-prompting and validates checkbox entries as bounded, de-duplicated numeric selections. Tests cover direct launcher dispatch, prompt behavior, and wheel metadata. The tool-local prompt test requires its dedicated test invocation, which is a non-blocking test-organization tradeoff.
No blocking issues. No inline issue met the actionable-evidence threshold; the assessment above records the review feedback.
Automated review; human maintainers own approval decisions.
| The template generator creates a working Cartpole task, its selected agent | ||
| configurations, and the packaging needed for the Isaac Lab CLI to discover it. | ||
| The quickest path is an external project: choose a name and workflow, run | ||
| ``uv sync``, and start the generated task with the Newton backend. | ||
|
|
||
| The generator runs entirely in the active Isaac Lab environment. It does not | ||
| invoke ``pip`` or install a second set of template dependencies, so it works in | ||
| the pip-less virtual environments created by ``uv``. |
There was a problem hiding this comment.
By reading this, it's not that clear to me what the template generator is used for.
I feel like it's missing the "why?".
There was a problem hiding this comment.
Addressed in 73db28d. The introduction now leads with why the generator exists: it bootstraps package structure, task registration, and agent configurations for either a standalone project or an upstream task.
AntoineRichard
left a comment
There was a problem hiding this comment.
Should this be accompanied with a skill?
| Build your own project or task | ||
| ============================== | ||
|
|
||
| The template generator creates a working Cartpole task, its selected agent |
There was a problem hiding this comment.
Leading with a "Cartpole task" feels weird too, this is a detail.
There was a problem hiding this comment.
Addressed in 73db28d. Cartpole is now introduced only after the general purpose, as the replaceable working example included by both generator modes.
| The quickest path is an external project: choose a name and workflow, run | ||
| ``uv sync``, and start the generated task with the Newton backend. | ||
|
|
||
| The generator runs entirely in the active Isaac Lab environment. It does not |
There was a problem hiding this comment.
This reads weird, does it? If we create an external project this is not the case?
There was a problem hiding this comment.
Clarified in 73db28d. This now sits next to the command and explicitly says the generator uses dependencies from the active Isaac Lab environment; it applies while creating an external project as well.
| Create and run a project | ||
| ------------------------ | ||
|
|
||
| First, :ref:`install Isaac Lab <isaaclab-installation-root>`. Run the generator | ||
| from the Isaac Lab source checkout or from a uv project that contains the | ||
| installed Isaac Lab package: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| uv run isaaclab --new | ||
|
|
||
| The short form is equivalent: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| uv run isaaclab -n | ||
|
|
||
| Select the following options for a small first project: | ||
|
|
||
| * **External** project | ||
| * A parent directory outside the Isaac Lab repository | ||
| * A Python-compatible project name, such as ``my_cartpole`` | ||
| * **Manager-based | single-agent** workflow | ||
| * **rsl_rl** with **PPO** | ||
|
|
||
| The prompts display the valid options and accept numbered, comma-separated | ||
| selections when more than one choice is allowed. The generator creates the | ||
| project under ``<parent-directory>/<project-name>`` and initializes a Git | ||
| repository there. | ||
|
|
||
| Enter the generated project and create its environment: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| cd <parent-directory>/my_cartpole | ||
| uv sync | ||
|
|
||
| This default environment includes the selected RL library and the kit-less | ||
| Newton backend. It does **not** install Isaac Sim. | ||
|
|
||
| List the generated task name and its available presets: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| uv run python scripts/list_envs.py --show_presets | ||
|
|
||
| Copy the task name from the output, then run a quick smoke test: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| uv run isaaclab random_agent --task <TASK_NAME> --num_envs 16 --viz newton | ||
|
|
||
| If the environment launches and the cart moves, the project is ready to edit. | ||
| You can then train and play a policy with the same command surface used by | ||
| Isaac Lab itself: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| uv run isaaclab train --rl_library rsl_rl --task <TASK_NAME> | ||
| uv run isaaclab play --rl_library rsl_rl --task <TASK_NAME> --checkpoint latest --viz newton |
There was a problem hiding this comment.
I don't like this split. I think the original doc did it better. Here we tell the user what to do without telling them why they are doing it. Leading with a: "Let's with creating an external project." would go be good. Even more if we explain the two options before!
There was a problem hiding this comment.
Addressed in 73db28d. The External/Internal comparison and workflow choices now come first, followed by an explicitly named external-project walkthrough.
| Choose a simulation backend | ||
| --------------------------- | ||
|
|
||
| Generated projects follow the same optional-extra model as Isaac Lab. Newton is | ||
| available after the default ``uv sync``; heavier simulator runtimes are only | ||
| installed when a command requests their extra. | ||
|
|
||
| .. list-table:: | ||
| :widths: 29 23 48 | ||
| :header-rows: 1 | ||
|
|
||
| * - Backend selector | ||
| - Required extra | ||
| - Example | ||
| * - ``physics=newton_mjwarp`` | ||
| - None | ||
| - ``uv run isaaclab random_agent --task <TASK_NAME> physics=newton_mjwarp`` | ||
| * - ``physics=newton_kamino`` | ||
| - None | ||
| - ``uv run isaaclab random_agent --task <TASK_NAME> physics=newton_kamino`` | ||
| * - ``physics=ovphysx`` | ||
| - ``ovphysx`` or ``ov`` | ||
| - ``uv run --extra ovphysx isaaclab random_agent --task <TASK_NAME> physics=ovphysx`` | ||
| * - ``physics=isaacsim_physx`` | ||
| - ``isaacsim`` | ||
| - ``uv run --extra isaacsim isaaclab random_agent --task <TASK_NAME> physics=isaacsim_physx`` | ||
|
|
||
| The ``ov`` extra installs both the OV PhysX and OVRTX runtimes. To combine | ||
| Newton physics with OVRTX rendering, request only the ``ovrtx`` extra: | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| uv run --extra ovrtx isaaclab random_agent --task <TASK_NAME> \ | ||
| physics=newton_mjwarp renderer=ovrtx | ||
|
|
||
| Place ``--extra`` before ``isaaclab``. Keep it on every command that needs the | ||
| optional runtime; this lets ``uv`` reproduce the intended environment without a | ||
| separate installation step. See :ref:`isaac-lab-quickstart` for all physics, | ||
| renderer, and visualizer combinations. |
There was a problem hiding this comment.
Does it make sense to have this here? Can't we just link the users to the different backends doc directly with a short note?
There was a problem hiding this comment.
Addressed in 73db28d. I replaced the backend matrix with a short note about the generated extras, one example, and links to Backends and Presets plus the quickstart combinations.
|
The ASCII tree in "Understand the generated project" is abbreviated in a way that hides the module layer, so a reader can't match it against what the generator actually writes. The doc shows: I ran Two things the tree stops short of: there's a task-family directory named after the project inside Suggest expanding the tree two levels so it matches the generator's output, and adding a line about the UI stub — it's the file people will most want to delete first. |
|
Small wording suggestion rather than a restructure: the Task layer currently reads as prescriptive —
That's a good description of one common shape, but it reads as the required one. I hit two cases where it doesn't fit while porting a 14-task locomotion family (MicroDuck) into a generated project:
The mechanism handles both fine — I put the shared package at Suggest saying |
|
The doc and the generator are both silent on tests, and generated projects ship no pytest configuration. Two things bit me carrying an existing suite (19 files, 598 tests) into a generated project:
Suggest the template gain a Unrelated to tests but in the same file, one more per-file-ignore would help: the template sets |
|
Splitting this out of my testing comment above, because it's the one thing in that bundle the doc can't fix on its own. External projects can't import the environment-test helpers. Lived consequence in the port: all 14 environment smoke tests in my generated project failed at collection with I've opened #7488 proposing the helpers move to an installed path (e.g. For this PR, either resolution seems fine: point the doc at a packaged home if #7488 lands, or say plainly that projects are expected to vendor |
|
run-ci |
|
Updated the template generator so our flagship choices are always option 1 when applicable:
Validated with Implemented in |
|
Aligned the external project template with
Validation:
The branch is also merged with the latest upstream |
|
run-ci |
AntoineRichard
left a comment
There was a problem hiding this comment.
Thanks I think it's great!
|
@StafaH do we want to backport this one? I would say yes. But it won't be QA tested? |
|
run-ci |
|
run-ci |
…erator-uv-pip # Conflicts: # source/isaaclab/test/cli/test_wheel_builder_metadata.py
|
run-ci |
…7480) (#7585) # Description Backports #7480 to `release/3.0.0` by cherry-picking merged commit `74839972bd890051f09f9d9535f476d3e532dc27` with `-x` provenance. The [automatic backport run](https://github.com/isaac-sim/IsaacLab/actions/runs/33917751795) encountered conflicts in the wheel-metadata regression test and `uv.lock`, then stopped because the combined conflict context exceeded the resolver limit. This manual backport preserves the release branch's wheel-builder helpers and installed-wheel compatibility dispatcher while adding the template dependency regression coverage. The lockfile retains the release dependency graph and records only the new direct Jinja2 requirement instead of importing `develop`'s unrelated marker normalization. | Field | Commit | |---|---| | Original merged change | `74839972bd890051f09f9d9535f476d3e532dc27` | | Release base used | `5c610f076e6e8ba251bd08275d1dbbc3f1353597` | | Proposed backport | `9d0b45f46d089854ee5e487e0931adce63276250` | ## Type of change - Bug fix (non-breaking change which fixes an issue) - Documentation update ## Release backport - [ ] <!-- backport-active-release --> This PR already targets the active release branch; do not backport it again. ## Validation - Repository backport candidate validation passed with every source path preserved and no extra paths changed. - `uv lock --check` passed with the release-specific lockfile resolution. - `uv run python -m pytest --confcutdir=tools/template tools/template/test_cli.py -q` — 7 passed. - `uv run python -m pytest source/isaaclab/test/cli/test_misc_commands.py source/isaaclab/test/cli/test_wheel_builder_metadata.py -q` — 18 passed. - `uv run python -m pytest source/isaaclab_rl/test/test_template_generator.py -q` — 20 passed. - `uv run isaaclab -f` passed. - `uv run --isolated --extra test -- make -C docs current-docs` passed without warnings. - `git diff --check upstream/release/3.0.0...HEAD` passed. ## Checklist - [x] I have read and understood the contribution guidelines. - [x] I have run the pre-commit checks. - [x] I have preserved the corresponding documentation changes. - [x] My changes generate no new warnings. - [x] I have preserved and run the regression tests. - [x] The original changelog fragments are preserved for both touched packages. - [x] The original contributors already exist in `CONTRIBUTORS.md`. Co-authored-by: Antoine Richard <antoiner@nvidia.com>
|
The uv lock seems to be geneated by an older version. @StafaH |
Description
The template generator attempted to install its dependencies with
python -m pipevery time it started. Fresh uv environments do not include the pip module, so the install failed and the generator then crashed while importing its prompt dependency.This change:
isaaclab --newisaacsim,ov,ovphysx, andovrtxas optional extras in generated projectsNo new prompt dependency is introduced: Jinja2 was already present transitively, while removing InquirerPy also removes its otherwise-unused
pfzydependency.Type of change
Release backport
developScreenshots
Not applicable.
Test plan
uv run python -m pytest --confcutdir=tools/template tools/template/test_cli.py -q(4 passed)uv run python -m pytest source/isaaclab/test/cli/test_misc_commands.py source/isaaclab/test/cli/test_wheel_builder_metadata.py -q(18 passed)isaacsimis a base dependencyuv run python tools/changelog/cli.py check developuv run isaaclab -fChecklist
uv run isaaclab -fisaaclabpackageCONTRIBUTORS.md