[CI] Skip the image invariants on a deps-cache hit and link _isaac_sim only in Kit images - #7540
Conversation
…y in Kit images The invariants step from isaac-sim#7405 inspects the commit-tagged image locally, but on a deps-cache hit ecr-build-push-pull only aliases that tag in ECR, so every first run of a new commit on a dependency-stable branch failed before any test job started. The action now reports whether it built the image and the step runs only then; a cache hit reuses an image that passed the check when it was built. run_tests.sh mounts runtime directories under /isaac-sim into every container, so the kit-less image has that directory too, and the unconditional _isaac_sim link made isaaclab.sh (isaac-sim#7466) treat it as a downloaded Isaac Sim next to the image's VIRTUAL_ENV. Link only where Kit's python.sh exists.
|
run-ci |
|
run-ci |
Greptile SummaryThe PR moves base-image invariant checks into the ECR action before its runnable-image push steps and avoids creating
Confidence Score: 4/5The PR is not yet safe to merge because legacy or previously verified dependency-cache manifests can still bypass the new image invariant. Dependency-cache hits alias the existing manifest to the commit tag and skip verification, while the cache key does not incorporate the verification gate or invariant test; therefore images created before the gate, or under an older invariant, remain eligible for downstream use. Files Needing Attention: .github/actions/ecr-build-push-pull/action.yml and .github/actions/_lib/compute-deps-hash/action.yml Important Files Changed
Reviews (3): Last reviewed commit: "Drop the digest binding from image verif..." | Re-trigger Greptile |
There was a problem hiding this comment.
Isaac Lab Review Bot
The _isaac_sim guard correctly preserves Kit-image behavior while unblocking the kit-less lane. However, the new built output conflates build freshness with local image availability, causing exact-tag reruns to skip image-invariant validation even though the image was pulled locally, and its documentation gives callers misleading guidance.
- Design and architecture: Avoiding a multi-GB pull on dependency-cache hits is reasonable, but build freshness is too coarse a gate for checks that require a locally available image. The action should distinguish the non-local dependency-cache path from fresh builds and exact-tag pulls.
- API: The additive
builtoutput is safe for existing callers, but its documented recommendation is inconsistent with its semantics: exact-tag hits and dependency hits withpull-on-deps-hitalso provide a local image while returningbuilt == 'false'. Restrict the documentation to build-only checks or expose a separate local-availability output. - Implementation: The
/isaac-sim/python.shprecondition andrm -fcorrectly avoid creating_isaac_simin kit-less images. Inbuild.yaml, however, gating invariants solely onbuilt == 'true'lets an exact-tag rerun pull an image that previously failed invariants and then skip the validation. The condition should include exact-tag local availability while exempting only dependency-cache hits that do not pull.
Minor fixes needed. Posted 2 actionable findings inline.
Automated review; human maintainers own approval decisions.
The invariants step ran after ecr-build-push-pull returned, but the action pushes the commit tag and the deps tag inside itself, so an image that fails the check is already in the shared cache. That happened four seconds apart on newton-world-prefixes (run 33735349483): the deps tag deps-6aebe721c56a91f7 was pushed at 09:05:07 and the invariant failed at 09:05:11, leaving an image whose Isaac Sim extensions cannot load. Any later run whose install inputs hash the same then gets a cache hit and inherits it, so gating the check on whether this run built the image would let the second push of the change that broke it go green. Move the assertion into the action, before every push, behind a verify-command input the base image job passes. A failure now publishes nothing, so the next run rebuilds and fails again. The built output added for the old gate is gone with it.
|
run-ci |
|
@greptileai review |
run-tests and run-package-tests take a test-path and own the pytest invocation; passing a whole shell command was a vocabulary of its own and put the runner's uv incantation in the caller.
|
run-ci |
The digest was read from the tag and compared with the same tag a second later, so it could not detect a stale tag. The verify step is now the same line the dockerfile-contract and kit-less validation jobs run, with only IMAGE_TAG set. The wiring test parses build.yaml instead of matching a substring a comment could satisfy.
|
@greptileai review |
|
run-ci |
# Description Fixes two release CI failures without backporting #7405. ## Kitless multi-GPU tests Backports only the release-relevant multi-GPU test fix from #7540. PR #7466 is present on `release/3.0.0`, so `isaaclab.sh` rejects a downloaded-Isaac-Sim link alongside the kitless image's active virtual environment. The test runner currently creates `_isaac_sim -> /isaac-sim` unconditionally because runtime mounts make `/isaac-sim` exist even in the kitless image. This change creates the link only when `/isaac-sim/python.sh` exists. Kit-based test images retain their existing behavior, while the kitless multi-GPU smoke test resolves Python from `VIRTUAL_ENV`. This intentionally excludes #7540's image-invariant/cache changes and all of #7405, which was not backported to the release branch. Original PR: #7540 ## Documentation link check The automatic backport's link check failed twice because `www.ros.org` and `docs.ros.org` return HTTP 403 to the GitHub runner. Both links remain valid. The link-check workflow already excludes known crawl blockers, so this adds a single `ros.org` exclusion covering both hosts without changing the documentation destinations or weakening checks for other domains. Failed run: https://github.com/isaac-sim/IsaacLab/actions/runs/33828925399 ## Type of change - Bug fix (non-breaking change which fixes an issue) ## Release backport Not applicable: this PR directly targets `release/3.0.0`. ## Validation - Added a regression test that failed against the unmodified release branch and passes with the multi-GPU fix. - `uv run --no-project --with pytest --with pyyaml python -m pytest docker/test/test_container_profiles.py -q` - 14 passed. - `bash -n .github/actions/run-tests/run_tests.sh` - passed. - Parsed `.github/workflows/check-links.yml` with PyYAML and verified the exclusion matches both failing URLs. - Applicable file-scoped pre-commit hooks - passed. The branch-wide changelog hook is not applicable to a release backport because it compares historical release differences against `develop`. - The canonical `uv run isaaclab -f` command cannot resolve this branch's Linux/Windows-only lockfile on macOS; the equivalent file-scoped hooks were run directly. ## Checklist - [x] I have read and understood the contribution guidelines. - [x] I have run the applicable pre-commit checks. - [x] Documentation destinations remain unchanged. - [x] My changes generate no new warnings. - [x] I have added a regression test for the multi-GPU behavior. - [x] No changelog fragment is required because no source package changed. - [x] The contributors already exist in `CONTRIBUTORS.md`. --------- Co-authored-by: hujc <jichuanh@nvidia.com>
Summary
Every first CI run of a new commit on a dependency-stable branch has failed since #7405 landed
(develop included):
Build Base Docker Imagedies in 20 s and skips the 17 test jobs behind it,and
Multi-GPU training smoke (kit-less)exits before pytest. Both are CI plumbing, fixed here.Description
1. Build Base Docker Image
#7405 added a "Verify image invariants" step that runs
docker image inspecton the commit tagafter
ecr-build-push-pull. The action leaves an image on the runner only after a full build or anexact-tag pull. On a deps-cache hit it just aliases the commit tag onto the
deps-<hash>manifest inECR and pulls nothing, so the inspect fails:
develop runs 33733992373, 33740164999 and 33781460422 fail this way; PRs pass only after a deps
change (full build) or on a re-run of an already built head (exact-tag pull).
The step also ran too late to be a gate. The action pushes the commit tag and the deps tag inside
itself, so an image that fails the check is already published. That is not hypothetical: on
newton-world-prefixes(run 33735349483)deps-6aebe721c56a91f7was pushed at 09:05:07 and theinvariant failed at 09:05:11, leaving an image whose Isaac Sim extensions cannot load in the shared
cache. Any later run whose install inputs hash the same inherits it.
Fix: move the assertion into the action, before every push, behind a
verify-commandinput that thebase image job passes. A failure now publishes nothing, so the next run rebuilds and fails again
rather than serving the bad image from the cache. Skipping it on a cache hit is then correct by
construction — every published image passed when it was built, and the deps hash covers exactly the
install inputs the invariant asserts against.
2. Multi-GPU training smoke (kit-less)
run_tests.shbind-mounts nine writable runtime directories under/isaac-sim/…into everycontainer, so
/isaac-simexists as a directory in the kit-less image too, and the container scriptthen runs
ln -s /isaac-sim _isaac_simunconditionally. #7466 taughtisaaclab.shto treat a_isaac_simdirectory without a source-build marker as a downloaded Isaac Sim and to refuse it nextto an active venv; the kit-less image sets
VIRTUAL_ENV=/opt/isaaclab-venv, so every run stops with:#7405 reworked the same check (venv-on-bundled-Python exemption) and the run-tests script without
exempting the kit-less lane. Every PR's smoke run since 11:43Z on 2026-09-03 fails identically.
Fix: plant the link only when
/isaac-sim/python.shexists. Kit images are unchanged; the kit-lessimage resolves its interpreter through
VIRTUAL_ENV, as it did before #7466.3. Audit of every
_isaac_simsiteEvery place that creates the link, and how it interacts with the guard:
run-tests/run_tests.sh/isaac-simin every imagepython.shmulti-gpu/multi_gpu_host_launcher.sh/isaac-sim, unguardedCI_IMAGE_TAG, the Kit image. The kit-less lane goes throughrun-testsDockerfile.base,Dockerfile.curoboISAACSIM_ROOT_PATH, alongsideVIRTUAL_ENVUV_PYTHON=${ISAACSIM_ROOT_PATH}/kit/python/bin/python3, so the venv is on the bundled Python and #7405's exemption appliesDockerfile.kitlesstest ! -e "${ISAACLAB_PATH}/_isaac_sim"cli/commands/misc.py(--isaacsim_source).isaaclab_source_builddocs/.../installation/index.rst×3ln -s4. Verification
docker/test/test_container_profiles.pygains two regression tests — one pinning the kit-lessguard, one pinning that verification precedes both push steps. Each fails without its fix. 15 pass
in that file, 20 with
test_carb_env_shim.py.yaml.safe_loadon both YAML files,bash -non the script, pre-commit on the changed files..github/actions/{ecr-build-push-pull,run-tests}/andbuild.yaml, which thedetect-changes patterns of both workflows match, so its own CI exercises both paths: the base image
job takes the deps-cache-hit path (no dependency change here) and the kit-less smoke job runs.
5. Out of scope
Three checkers implement the same "downloaded Isaac Sim vs. virtual environment" rule and #7405
updated only two, leaving user-facing divergences that this PR does not touch:
isaaclab.bathas neither the venv-on-bundled-Python exemption nor the--isaacsim_sourceescape, so on Windows the remedy the Linux error message recommends is still rejected.
cli/commands/envs.py::_reject_downloaded_isaac_simhas no exemption either, soisaaclab -c/-urejects a venv created on the bundled Python thatisaaclab.shaccepts.ln -s, which leaves no.isaaclab_source_buildmarker, so the same tree is treated as "downloaded" unless linked via
--isaacsim_source.isaaclab.shalso lacks thepython.shprecondition its Python twin (cli/utils.py) has, butthat is deliberate:
test_launcher_rejects_downloaded_isaac_sim_with_active_environmentpins thefail-closed behaviour on a bare directory. That is why the fix here is in the CI script.
Type of change
Release backport
developChecklist
pre-commitchecks with./isaaclab.sh --formatCONTRIBUTORS.mdor my name already exists there