Skip to content

[Fix] Pin Newton to the commit carrying newton#4017 - #7445

Draft
hujc7 wants to merge 28 commits into
isaac-sim:developfrom
hujc7:jichuanh/newton-pin-4017-uvlock
Draft

[Fix] Pin Newton to the commit carrying newton#4017#7445
hujc7 wants to merge 28 commits into
isaac-sim:developfrom
hujc7:jichuanh/newton-pin-4017-uvlock

Conversation

@hujc7

@hujc7 hujc7 commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Description

resolve_fixed_tendon_actuator_columns reads mujoco.actuator_trntype through an
ArticulationView. Every Newton 1.5.x release rejects that with "has custom frequency
'mujoco:actuator' which is not supported by ArticulationView"
; newton#4017 makes
ArticulationView generic over custom frequencies.

The fix is on main and in no 1.5.x release — verified against release-1.5, the v1.5.1
tag, and v1.5.0, all of which still carry the pre-fix rejection string, and PyPI, whose
latest newton is 1.5.1. The pin therefore moves from the PyPI release form back to a git
commit, and Newton reports 1.6.0.dev0.

Three pin sites mirror each other and are updated together:

  • [tool.uv].override-dependencies in the root pyproject.toml
  • tools/wheel_builder/uv-overrides.txt
  • source/isaaclab/test/install_ci/uv_pip/uv-overrides.txt

isaaclab.sh --install needs no change: #7405's _ensure_newton already parses both the
@<sha> and ==<version> pin forms.

Type of change

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

Release backport

  • Backport this pull request to the active release branch after it merges into develop

Checklist

hujc7 added 18 commits August 28, 2026 02:11
Adds a composable teleop-no-isaacsim extra so the lock path selects the teleop
requirements without pulling the isaacsim wheel into an image that already ships
Kit. Derives the submodule extras from OPTIONAL_SUBMODULE_ROOT_EXTRAS instead of a
second hardcoded table, and falls back to pip rather than installing less than was
asked for. Pins the uv pip calls to the venv: UV_PYTHON selects the target
environment, so they were writing into Isaac Sim's site-packages.
Reverts the install CLI lock path: it also caught Conda environments, where uv
sync targets the project environment rather than the active one, breaking the
install_ci Conda tests. The images control VIRTUAL_ENV and UV_PROJECT_ENVIRONMENT
themselves, so Dockerfile.base syncs the lock directly through a named kit-image
extra. imageio-ffmpeg is excluded during the sync instead of uninstalled after.
The extras set gained teleop-no-isaacsim and kit-image. teleop now composes from
the former, so asserting on its literal requirement list no longer sees
isaaclab-mimic; flatten the isaaclab-dev[...] self-reference first so the contract
stays on what the extra resolves to.
run_tests.sh launches the test container with --user ${host_uid}:${host_gid}, so a
venv owned by the image's own user is read-only there and the test-time extras
install (pytetwild for tetrahedralization) fails with EACCES. Widen the mode
instead of chowning to a uid the image cannot know.
The teleop extra now composes through an isaaclab-dev[teleop-no-isaacsim]
self-reference. _root_extra_dependencies strips every isaaclab* requirement as a
workspace self-reference and isaacsim separately, so the list came back empty and
./isaaclab.sh -i teleop installed none of the teleop stack.

Expand root self-references before the workspace filter runs, guarding against a
cycle with a seen set.
The test extra pulls the whole Sphinx docs stack, so the images installed a bare
pytest and CI layered pytest-mock, junitparser, flaky and coverage on top in a
separate post-build docker build.

Split those runners into a test-runtime extra that test composes from, and pull it
into kit-image so both images carry them from the lock. In-image pytest goes from
238 passed / 23 failed to 257 passed / 4 failed; the 4 remaining fail identically
without this change.
Restore the uv cache mount and drop UV_NO_CACHE=1, which disabled the only
working build cache. Resolve the third-party packages from workspace manifests
above the source copy so a source edit re-runs only the workspace install
(240 packages in 6.0s -> 14 in 4ms).

Set ownership in the layer that creates the venv instead of a recursive chown
afterwards: on overlayfs a chown copies up every file it touches, so the base
image stored the 11.5GB venv twice. That layer drops from 1003.9s to 36.1s and
the image from 44.7GB to 33.2GB, with 0 of 98562 common files differing in owner
or mode. Kit-less sets the modes in its builder stage so the stage copy carries
them rather than adding an equivalent layer.

Also hoist the layers that depend on no repo content above the copies, give
isaaclab.sh an explicit 755 (sed -i rewrote it under the build umask, leaving it
unrunnable by other uids), and keep local ruff/pytest caches out of the context.
test_dockerfile_nonroot.py only globs Dockerfile.* and parses their text, but
build.yaml ran it inside the image via /isaac-sim/python.sh in both the
isaaclab_ov and curobo jobs. Kit's interpreter has no pytest once the install
moves to the venv, so those steps failed, and a text lint held a self-hosted GPU
runner in two places.

Move it to a ubuntu-latest job using the invocation kitless-docker.yml already
uses. The steps that verify the running container's uid stay where they are.
Two assumptions broke when the install moved into a venv.

The uv path was derived from site.getuserbase() and bootstrapped with pip install
uv, which only landed there because Isaac Sim's site-packages was read-only; pip
installs into the venv's own bin instead, so $HOME/.local/bin/uv never appeared
and record-video died with No such file or directory. Prefer uv from PATH, which
the image ships, and keep the user-base bootstrap for images that do not.

The [INFO] banner isaaclab.sh writes to stdout now follows the command output
rather than preceding it, so tail -n 1 captured the banner for the interpreter,
user-site and uv paths. Filter the banner instead of skipping by position.
Isaac Sim ships prebundled copies under pip_prebundle that setup_python_env.sh
puts on PYTHONPATH. isaaclab.sh deprioritizes them, but launch paths that never
import isaaclab (runheadless.sh, isaac-sim.streaming.sh) do not, and the
prebundled torch loads a libtorch_cuda.so needing an NCCL symbol the bundled
NCCL does not export (nvbugs 6343978).

The pip install path repointed them itself; installing into a venv leaves them
untouched, so test_no_shadowing_prebundled_torch_in_isaac_sim failed. Reuse the
same repoint after the workspace sync, while the build is still root: 17
packages become symlinks into the venv and the shadowing directory count drops
to 0.
The MuJoCo tendon adapter reads mujoco.actuator_trntype through an
ArticulationView, which every Newton 1.5.x release rejects with "has custom
frequency 'mujoco:actuator' which is not supported by ArticulationView".
newton#4017 makes ArticulationView generic over custom frequencies.

The fix landed on main and is in no 1.5.x release, so the pin moves from the
PyPI form to the merge commit and Newton reports 1.6.0.dev0. Regenerating
uv.lock is what carries the pin into the Docker images.
@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team infrastructure labels Aug 31, 2026
@hujc7 hujc7 added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Aug 31, 2026
The install CI hard-coded ``m.version('newton') == '1.5.1'``, which the pin bump
breaks. Read the requirement from [tool.uv].override-dependencies and compare the
commit recorded in the distribution's direct_url.json, so the assertion follows a
bump rather than going stale on every one.

A version string cannot identify the pin: every commit on Newton's main branch
reports the same 1.6.0.dev0.
@hujc7 hujc7 added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Aug 31, 2026
hujc7 added 3 commits August 31, 2026 00:10
This reverts commit 3037385.

The premise was wrong. That test installs with ``uv pip install <wheel>[all]``
and no overrides file, so Newton resolves from PyPI against the wheel's loose
``newton[sim]>=1.2.0`` bound -- 1.5.1, recorded without a direct_url.json. The
git pin only reaches ``uv sync`` paths, so it does not change what this test
sees, and asserting the pinned commit here made the assertion unsatisfiable.
The images excluded imageio-ffmpeg, so moviepy.editor - which
isaaclab/envs/utils/video_recorder.py imports - fell through to imageio's TIFF
writer and raised TypeError on write. Video recording only worked because CI
installs moviepy into the container at test time.

Pull the existing video extra into kit-image and drop the exclusion. Costs
31.6 MB (moviepy, imageio-ffmpeg, proglog) on a 33 GB image; verified in-image
that ImageSequenceClip.write_videofile produces a real mp4.
@hujc7 hujc7 added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Aug 31, 2026
@hujc7 hujc7 added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Aug 31, 2026
hujc7 added 3 commits August 31, 2026 04:51
The pinned Newton rejects a non-"fixed" penalty_update_method unless
sparse_dynamics is set, and sparse dynamics in turn require a sparse Jacobian
(solver_kamino.py:397 and :439). The round-trip test built the default
combination, so to_solver_config() raised before any field could be checked.

Set both sparse flags in the test. They are valid for every parametrized field,
and the test asserts field forwarding rather than solver-combination validity.
Isaac Sim ships some prebundled packages twice: a flat directory and an
extras-qualified mirror, <pkg>[extras]/<pkg>-<version>-*/<pkg>, whose contents
are per-file symlinks into the flat copy. Only the flat directory was
repointed, so the mirror kept pointing at the shipped version file list.

MEASURED on the Isaac Sim image: newton[sim]/newton-1.5.0-py3-none-any/newton
holds 842 symlinks, and 330 of their targets do not exist in the newton the
pin installs, 232 of them under _src/solvers/kamino. The install then aborts
on its own dangling-symlink guard, which is correct: extensions resolving
through the mirror would hit missing modules at runtime.

Collapse each mirror to the same symlink the flat directory already gets, so
one directory link replaces a per-file tree that goes stale on every bump.
Mirrors are matched by name rather than glob, since newton[sim] is a valid
character class that would otherwise match newtons.
@hujc7 hujc7 added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation infrastructure isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant