Skip to content

[CI] Skip the image invariants on a deps-cache hit and link _isaac_sim only in Kit images - #7540

Merged
kellyguo11 merged 5 commits into
isaac-sim:developfrom
hujc7:jichuanh/ci-deps-hit-invariants-kitless-smoke
Sep 4, 2026
Merged

[CI] Skip the image invariants on a deps-cache hit and link _isaac_sim only in Kit images#7540
kellyguo11 merged 5 commits into
isaac-sim:developfrom
hujc7:jichuanh/ci-deps-hit-invariants-kitless-smoke

Conversation

@hujc7

@hujc7 hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Every first CI run of a new commit on a dependency-stable branch has failed since #7405 landed
(develop included): Build Base Docker Image dies 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 inspect on the commit tag
after ecr-build-push-pull. The action leaves an image on the runner only after a full build or an
exact-tag pull. On a deps-cache hit it just aliases the commit tag onto the deps-<hash> manifest in
ECR and pulls nothing, so the inspect fails:

Error response from daemon: No such image: isaac-lab-ci:develop-8ca264bd8e5528d7d9b7b6f58a9d8cd051c5933a

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-6aebe721c56a91f7 was pushed at 09:05:07 and the
invariant 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-command input that the
base 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.sh bind-mounts nine writable runtime directories under /isaac-sim/… into every
container, so /isaac-sim exists as a directory in the kit-less image too, and the container script
then runs ln -s /isaac-sim _isaac_sim unconditionally. #7466 taught isaaclab.sh to treat a
_isaac_sim directory without a source-build marker as a downloaded Isaac Sim and to refuse it next
to an active venv; the kit-less image sets VIRTUAL_ENV=/opt/isaaclab-venv, so every run stops with:

[ERROR] Downloaded Isaac Sim packages cannot be combined with a Python virtual environment.

#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.sh exists. Kit images are unchanged; the kit-less
image resolves its interpreter through VIRTUAL_ENV, as it did before #7466.

3. Audit of every _isaac_sim site

Every place that creates the link, and how it interacts with the guard:

Site Creates Verdict
run-tests/run_tests.sh /isaac-sim in every image Fixed here: guarded on python.sh
multi-gpu/multi_gpu_host_launcher.sh /isaac-sim, unguarded Correct today: its only caller passes CI_IMAGE_TAG, the Kit image. The kit-less lane goes through run-tests
Dockerfile.base, Dockerfile.curobo ISAACSIM_ROOT_PATH, alongside VIRTUAL_ENV Correct: UV_PYTHON=${ISAACSIM_ROOT_PATH}/kit/python/bin/python3, so the venv is on the bundled Python and #7405's exemption applies
Dockerfile.kitless never; asserts test ! -e "${ISAACLAB_PATH}/_isaac_sim" Correct
cli/commands/misc.py (--isaacsim_source) source-build link Correct: writes .isaaclab_source_build
docs/.../installation/index.rst ×3 user-run ln -s Out of scope, see below

4. Verification

  • docker/test/test_container_profiles.py gains two regression tests — one pinning the kit-less
    guard, 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_load on both YAML files, bash -n on the script, pre-commit on the changed files.
  • This PR touches .github/actions/{ecr-build-push-pull,run-tests}/ and build.yaml, which the
    detect-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.bat has neither the venv-on-bundled-Python exemption nor the --isaacsim_source
    escape, so on Windows the remedy the Linux error message recommends is still rejected.
  • cli/commands/envs.py::_reject_downloaded_isaac_sim has no exemption either, so
    isaaclab -c/-u rejects a venv created on the bundled Python that isaaclab.sh accepts.
  • The docs link a source build with a bare ln -s, which leaves no .isaaclab_source_build
    marker, so the same tree is treated as "downloaded" unless linked via --isaacsim_source.

isaaclab.sh also lacks the python.sh precondition its Python twin (cli/utils.py) has, but
that is deliberate: test_launcher_rejects_downloaded_isaac_sim_with_active_environment pins the
fail-closed behaviour on a bare directory. That is why the fix here is in the CI script.

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

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation (the action README documents the new output)
  • My changes generate no new warnings
  • Tests: CI-only change; the workflows' own runs on this PR are the test
  • Changelog: no source package changed
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

…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.
@github-actions github-actions Bot added documentation Improvements or additions to documentation infrastructure labels Sep 3, 2026
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot 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 Sep 3, 2026
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot 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 Sep 3, 2026
@hujc7
hujc7 marked this pull request as ready for review September 3, 2026 20:15
@hujc7
hujc7 requested a review from a team September 3, 2026 20:15
@greptile-apps

greptile-apps Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR moves base-image invariant checks into the ECR action before its runnable-image push steps and avoids creating _isaac_sim in kit-less test containers.

  • Adds an optional fresh-build verification test path to the ECR action.
  • Makes the run-tests symlink conditional on an executable Isaac Sim python.sh.
  • Adds regression coverage for publication ordering and kit-less behavior.

Confidence Score: 4/5

The 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

Filename Overview
.github/actions/ecr-build-push-pull/action.yml Adds pre-push verification for fresh builds, but existing dependency-cache manifests remain exempt and can still be promoted without verification.
.github/actions/run-tests/run_tests.sh Restricts _isaac_sim creation to images that actually contain the Kit Python launcher.
.github/workflows/build.yaml Delegates the base-image invariant test to the reusable ECR action.
docker/test/test_container_profiles.py Adds structural regression tests covering verification ordering and conditional symlink creation.
docker/test/test_image_invariants.py Removes the obsolete digest-binding assertion now that verification runs directly after the local build.

Reviews (3): Last reviewed commit: "Drop the digest binding from image verif..." | Re-trigger Greptile

Comment thread .github/workflows/build.yaml Outdated
Comment thread .github/actions/ecr-build-push-pull/action.yml Outdated

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

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.

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 built output is safe for existing callers, but its documented recommendation is inconsistent with its semantics: exact-tag hits and dependency hits with pull-on-deps-hit also provide a local image while returning built == 'false'. Restrict the documentation to build-only checks or expose a separate local-availability output.
  • Implementation: The /isaac-sim/python.sh precondition and rm -f correctly avoid creating _isaac_sim in kit-less images. In build.yaml, however, gating invariants solely on built == '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.

Comment thread .github/workflows/build.yaml Outdated
Comment thread .github/actions/ecr-build-push-pull/action.yml Outdated
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.
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot 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 Sep 3, 2026
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@greptileai review

Comment thread .github/actions/ecr-build-push-pull/action.yml
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.
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot 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 Sep 3, 2026
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.
@hujc7 hujc7 added the ci:run-docker Trigger the on-demand Docker and GPU CI workflow label Sep 3, 2026
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@greptileai review

@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot 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 Sep 3, 2026
@kellyguo11
kellyguo11 merged commit df44b19 into isaac-sim:develop Sep 4, 2026
56 of 83 checks passed
kellyguo11 added a commit that referenced this pull request Sep 4, 2026
# 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>
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants