Skip to content

Fix the cable being culled by its scene partition in the Franka cable… #12275

Fix the cable being culled by its scene partition in the Franka cable…

Fix the cable being culled by its scene partition in the Franka cable… #12275

Workflow file for this run

# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# region help
# Every test job runs on every PR and merge queue candidate. Pushes to protected branches run the
# post-merge integration tests.
#
# =============================================================================
# CI DEBUGGING TIPS
# =============================================================================
#
# 1. DISABLE A TEST JOB (to isolate a specific job):
# Change the job's `if:` clause to `if: false`
# Example:
# test-isaaclab-tasks:
# ...
# if: false # TEMP: Disabled for debugging
#
# 2. RUN ONLY SPECIFIC TEST FILES (within a job):
# Add `include-files:` parameter to run-package-tests action
# Example:
# - uses: ./.github/actions/run-package-tests
# with:
# ...
# include-files: "test_rigid_object_collection.py" # Comma-separated
#
# 3. SKIP CONCURRENCY WAIT (run immediately without waiting for other runs):
# Comment out the concurrency block:
# # concurrency:
# # group: ${{ github.workflow }}-${{ github.ref }}
# # cancel-in-progress: true
#
# 4. TEST LOCALLY LIKE CI:
# docker run -it --rm --gpus all --network=host --entrypoint bash \
# -e OMNI_KIT_ACCEPT_EULA=yes -e ACCEPT_EULA=Y -e ISAAC_SIM_HEADLESS=1 \
# -e TEST_FILTER_PATTERN="isaaclab_physx" \
# -e TEST_INCLUDE_FILES="test_rigid_object_collection.py" \
# -v "$PWD":/workspace/isaaclab isaac-lab-base:latest \
# -c 'cd /workspace/isaaclab && /isaac-sim/python.sh -m pytest tools -v'
#
# Remember to REVERT all temporary changes before merging!
# =============================================================================
#endregion
name: Docker + Tests
on:
push:
branches:
- main
- develop
- 'release/**'
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
- develop
- 'release/**'
workflow_dispatch:
# Concurrency control to prevent parallel runs on the same PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
pull-requests: write
checks: write
issues: read
env:
NGC_API_KEY: ${{ secrets.NGC_API_KEY }}
jobs:
changes:
name: Detect Changes
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.detect.outputs.should_run }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
sparse-checkout: .github/actions/detect-changes
sparse-checkout-cone-mode: false
- id: detect
uses: ./.github/actions/detect-changes
with:
triggered-jobs-push: "Docker base build job + rendering-correctness + rendering-correctness-kitless + warp-cache-warm"
triggered-jobs-pr: "Docker build jobs + all test-* matrix jobs"
# config.yaml is included because it controls the base image names and tags
# consumed by the Docker build jobs.
patterns: |
^source/ :: Library source code
^docker/ :: Container build inputs
^tools/ :: Build tooling
^apps/ :: Standalone apps
^scripts/ :: Standalone scripts
^\.dockerignore$ :: Docker build context filter
^conftest\.py$ :: Root pytest configuration
^pyproject\.toml$ :: Root Python project (Docker copy)
^environment\.yml$ :: Conda env (Docker copy)
^isaaclab\. :: isaaclab.sh/.bat entrypoints (Docker copy)
^\.github/workflows/build\.yaml$ :: This workflow file
^\.github/workflows/config\.yaml$ :: Shared CI config
^\.github/actions/ :: CI actions
^\.github/test-subsets/ :: CI test subset config
config:
name: Load Config
runs-on: ubuntu-latest
outputs:
isaacsim_image_name: ${{ steps.load.outputs.isaacsim_image_name }}
isaacsim_image_tag: ${{ steps.load.outputs.isaacsim_image_tag }}
isaaclab_image_name: ${{ steps.load.outputs.isaaclab_image_name }}
ovphysx_wheelhouse_image: ${{ steps.load.outputs.ovphysx_wheelhouse_image }}
ci_image_tag: ${{ steps.image_tag.outputs.ci_image_tag }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
sparse-checkout: .github/workflows/config.yaml
sparse-checkout-cone-mode: false
- id: load
run: |
set -euo pipefail
f=.github/workflows/config.yaml
echo "isaacsim_image_name=$(yq -r .isaacsim_image_name "$f")" >> "$GITHUB_OUTPUT"
echo "isaacsim_image_tag=$(yq -r .isaacsim_image_tag "$f")" >> "$GITHUB_OUTPUT"
echo "isaaclab_image_name=$(yq -r .isaaclab_image_name "$f")" >> "$GITHUB_OUTPUT"
echo "ovphysx_wheelhouse_image=$(yq -r '.ovphysx_wheelhouse_image // ""' "$f")" >> "$GITHUB_OUTPUT"
# NOTE: this ci_image_tag formula is intentionally duplicated in arm-ci.yml's
# config job — the two images are independent (x86 here vs -arm64 there), so
# they are not shared. Keep the two formulas in sync if either changes.
- id: image_tag
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REF_NAME: ${{ github.ref_name }}
SHA: ${{ github.sha }}
run: |
set -euo pipefail
if [ "$EVENT_NAME" = "pull_request" ]; then
ref_component="pr-${PR_NUMBER}"
else
ref_component="$REF_NAME"
fi
# Sanitize the ref name for use as a Docker tag suffix.
sanitized_ref=$(echo "$ref_component" | sed 's/[^a-zA-Z0-9._-]/-/g')
echo "ci_image_tag=isaac-lab-ci:${sanitized_ref}-${SHA}" >> "$GITHUB_OUTPUT"
echo "CI image tag: isaac-lab-ci:${sanitized_ref}-${SHA}"
#region build jobs
build:
name: Build Base Docker Image
runs-on: [self-hosted, gpu]
needs: [changes, config]
if: needs.changes.outputs.should_run == 'true'
steps:
- name: Checkout Code
uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- name: Build and push to ECR
uses: ./.github/actions/ecr-build-push-pull
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
dockerfile-path: docker/Dockerfile.base
cache-tag: cache-base
build-curobo:
name: Build cuRobo Docker Image
runs-on: [self-hosted, gpu]
needs: [changes, config]
if: >-
github.event_name != 'push' &&
needs.changes.outputs.should_run == 'true'
steps:
- name: Checkout Code
uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- name: Build and push to ECR
uses: ./.github/actions/ecr-build-push-pull
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}-curobo
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
dockerfile-path: docker/Dockerfile.curobo
cache-tag: cache-curobo
#endregion
#region test jobs
test-isaaclab-tasks:
name: isaaclab_tasks [1/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
continue-on-error: true
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
exclude-pattern: "test_rendering_,test_video_recording.py"
extra-pip-packages: "pytetwild[all]>=0.3.0,<0.4"
shard-index: "0"
shard-count: "3"
warp-cache: restore
container-name: isaac-lab-tasks-1-test
test-isaaclab-tasks-2:
name: isaaclab_tasks [2/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
continue-on-error: true
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
exclude-pattern: "test_rendering_,test_video_recording.py"
extra-pip-packages: "pytetwild[all]>=0.3.0,<0.4"
shard-index: "1"
shard-count: "3"
warp-cache: restore
container-name: isaac-lab-tasks-2-test
test-isaaclab-tasks-3:
name: isaaclab_tasks [3/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
continue-on-error: true
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
exclude-pattern: "test_rendering_,test_video_recording.py"
extra-pip-packages: "pytetwild[all]>=0.3.0,<0.4"
shard-index: "2"
shard-count: "3"
warp-cache: restore
container-name: isaac-lab-tasks-3-test
test-isaaclab-core:
name: isaaclab (core) [1/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "not isaaclab_"
shard-index: "0"
shard-count: "3"
warp-cache: restore
container-name: isaac-lab-core-1-test
test-isaaclab-core-2:
name: isaaclab (core) [2/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "not isaaclab_"
shard-index: "1"
shard-count: "3"
warp-cache: restore
container-name: isaac-lab-core-2-test
test-isaaclab-core-3:
name: isaaclab (core) [3/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "not isaaclab_"
shard-index: "2"
shard-count: "3"
warp-cache: restore
container-name: isaac-lab-core-3-test
# Kit and non-Kit are written out rather than expressed as a matrix: these job
# names are required status checks, and a skipped matrix job publishes its
# check run with the matrix expression unexpanded, so the required context
# never appears and branch protection blocks the pull request.
test-standalone-demos-kit:
name: standalone demos (headless, Kit)
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
# deformables.py tetrahedralizes its volume meshes at startup
extra-pip-packages: "pytetwild[all]>=0.3.0,<0.4"
include-files: "test_standalone_scripts.py"
standalone-script-scope: "demos"
standalone-script-visualizer: "none"
standalone-script-runtime-group: kit
result-file: "test-standalone-demos-kit-report.xml"
container-name: isaac-lab-standalone-demos-kit-test
omni-github-test-type: standalone-demo
test-standalone-demos-non-kit:
name: standalone demos (headless, non-Kit)
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- name: Resolve OVPhysX runtime pin from pyproject
uses: ./.github/actions/resolve-ov-pins
id: ov_pins
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
# deformables.py tetrahedralizes its volume meshes at startup
extra-pip-packages: >-
pytetwild[all]>=0.3.0,<0.4
${{ steps.ov_pins.outputs.ovphysx }}
include-files: "test_standalone_scripts.py"
standalone-script-scope: "demos"
standalone-script-visualizer: "none"
standalone-script-runtime-group: non-kit
result-file: "test-standalone-demos-non-kit-report.xml"
container-name: isaac-lab-standalone-demos-non-kit-test
omni-github-test-type: standalone-demo
test-isaaclab-rl:
name: isaaclab_rl
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_rl"
extra-pip-packages: "leapp"
container-name: isaac-lab-rl-test
test-isaaclab-mimic:
name: isaaclab_mimic
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_mimic"
container-name: isaac-lab-mimic-test
test-isaaclab-contrib:
name: isaaclab_contrib
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_contrib"
extra-pip-packages: "pytetwild[all]>=0.3.0,<0.4"
container-name: isaac-lab-contrib-test
test-isaaclab-teleop:
name: isaaclab_teleop
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_teleop"
container-name: isaac-lab-teleop-test
test-isaaclab-visualizers:
name: isaaclab_visualizers
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_visualizers"
container-name: isaac-lab-visualizers-test
test-isaaclab-assets:
name: isaaclab_assets
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_assets"
container-name: isaac-lab-assets-test
test-isaaclab-experimental:
name: isaaclab_experimental
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_experimental"
container-name: isaac-lab-experimental-test
test-isaaclab-newton:
name: isaaclab_newton
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_newton"
warp-cache: restore
container-name: isaac-lab-newton-test
test-isaaclab-physx:
name: isaaclab_physx
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_physx"
extra-pip-packages: "pytetwild[all]>=0.3.0,<0.4"
container-name: isaac-lab-physx-test
test-isaaclab-ov:
name: isaaclab_ov
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
env:
USE_OVPHYSX_WHEELHOUSE: ${{ needs.config.outputs.ovphysx_wheelhouse_image != '' && ((github.event_name == 'pull_request' && github.base_ref == 'develop' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name != 'pull_request' && github.ref_name == 'develop')) }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- name: Resolve OV runtime pins from pyproject
uses: ./.github/actions/resolve-ov-pins
id: ov_pins
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_ov"
# Volume deformable tests tetrahedralize their meshes at startup.
extra-pip-packages: pytetwild[all]>=0.3.0,<0.4 ${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && steps.ov_pins.outputs.ovrtx || format('{0} {1}', steps.ov_pins.outputs.ovrtx, steps.ov_pins.outputs.ovphysx) }}
wheelhouse-image: ${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && needs.config.outputs.ovphysx_wheelhouse_image || '' }}
wheelhouse-packages: ${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && 'ovphysx' || '' }}
container-name: isaac-lab-ov-test
# Folded from the former standalone verify-base-non-root job: reuses the
# base image already pulled by run-package-tests to keep the regression
# check without burning a separate runner.
- name: Run Dockerfile non-root regression test
shell: bash
run: |
set -euo pipefail
docker run --rm \
-v "$PWD":/workspace/isaaclab \
--entrypoint bash \
"${{ needs.config.outputs.ci_image_tag }}" \
-lc 'cd /workspace/isaaclab && /isaac-sim/python.sh -m pytest docker/test/test_dockerfile_nonroot.py -q'
- name: Verify Base runtime user is non-root
shell: bash
run: |
set -euo pipefail
runtime_identity="$(docker run --rm --entrypoint bash "${{ needs.config.outputs.ci_image_tag }}" \
-lc 'printf "%s %s %s\n" "$(id -u)" "$(id -g)" "$(id -un 2>/dev/null || true)"')"
read -r runtime_uid runtime_gid runtime_user <<< "${runtime_identity}"
echo "Base runtime identity: uid=${runtime_uid} gid=${runtime_gid} user=${runtime_user}"
if [ "${runtime_uid}" = "0" ]; then
echo "::error::Base Docker image must not run as root by default."
exit 1
fi
test-curobo:
name: test-curobo
runs-on: [self-hosted, gpu]
timeout-minutes: 120
continue-on-error: true
needs: [build-curobo, config]
if: >-
github.event_name != 'push' &&
needs.build-curobo.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}-curobo
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
dockerfile-path: docker/Dockerfile.curobo
cache-tag: cache-curobo
include-files: "test_curobo_planner_franka.py,test_curobo_planner_cube_stack.py,test_pink_ik.py"
container-name: isaac-lab-curobo-test
# Folded from the former standalone verify-curobo-non-root job: reuses
# the curobo image already pulled by run-package-tests to keep the
# regression check without burning a separate runner.
- name: Run Dockerfile non-root regression test
shell: bash
run: |
set -euo pipefail
docker run --rm \
-v "$PWD":/workspace/isaaclab \
--entrypoint bash \
"${{ needs.config.outputs.ci_image_tag }}-curobo" \
-lc 'cd /workspace/isaaclab && /isaac-sim/python.sh -m pytest docker/test/test_dockerfile_nonroot.py -q'
- name: Verify cuRobo runtime user is non-root
shell: bash
run: |
set -euo pipefail
runtime_identity="$(docker run --rm --entrypoint bash "${{ needs.config.outputs.ci_image_tag }}-curobo" \
-lc 'printf "%s %s %s\n" "$(id -u)" "$(id -g)" "$(id -un 2>/dev/null || true)"')"
read -r runtime_uid runtime_gid runtime_user <<< "${runtime_identity}"
echo "cuRobo runtime identity: uid=${runtime_uid} gid=${runtime_gid} user=${runtime_user}"
if [ "${runtime_uid}" = "0" ]; then
echo "::error::cuRobo Docker image must not run as root by default."
exit 1
fi
test-contrib-environments:
name: test-contrib-environments
runs-on: [self-hosted, gpu]
timeout-minutes: 120
continue-on-error: true
needs: [build-curobo, config]
if: >-
github.event_name != 'push' &&
needs.build-curobo.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}-curobo
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
dockerfile-path: docker/Dockerfile.curobo
cache-tag: cache-curobo
include-files: "test_generate_dataset_skillgen.py,test_contrib_environments.py"
container-name: isaac-lab-contrib-environments-test
test-record-video:
name: "record-video"
runs-on: [self-hosted, gpu]
timeout-minutes: 180
continue-on-error: true
needs: [build, config]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
include-files: "test_video_recording.py"
extra-uv-packages: "moviepy>=1.0.3,<2.0.0.dev0 decorator<5"
container-name: isaac-lab-record-video-test
omni-github-test-type: video-e2e
test-rendering-correctness:
name: "rendering-correctness"
runs-on: [self-hosted, gpu]
timeout-minutes: 120
continue-on-error: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }}
needs: [build, config]
if: needs.build.result == 'success'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
extra-pip-packages: "pytetwild[all]>=0.3.0,<0.4"
include-files: >-
test_rendering_cartpole.py,
test_rendering_lift_kuka_hetero.py,
test_rendering_lift_kuka_homo.py,
test_rendering_franka_cloth.py,
test_rendering_franka_soft.py,
test_rendering_franka_cable.py,
test_rendering_registered_tasks.py,
test_rendering_shadow_hand.py
test-node-ids-file: ${{ github.event_name == 'push' && '.github/test-subsets/postmerge-rendering.toml' || '' }}
test-node-ids-key: ${{ github.event_name == 'push' && 'rendering-correctness' || '' }}
warp-cache: restore
container-name: isaac-lab-rendering-correctness-test
omni-github-test-type: rendering-correctness
# Written out per variant rather than as a matrix: `rendering-correctness-kitless
# (legacy)` is a required status check, and a skipped matrix job publishes its
# check run with the matrix expression unexpanded. Writing the variants out also
# lets ovstage carry its own `if:`, which a matrix could only express through a
# synthetic event_name axis plus an exclude entry.
test-rendering-correctness-kitless-legacy:
name: "rendering-correctness-kitless (legacy)"
runs-on: [self-hosted, gpu]
timeout-minutes: 120
continue-on-error: ${{ github.event_name == 'workflow_dispatch' }}
needs: [build, config]
if: needs.build.result == 'success'
env:
USE_OVPHYSX_WHEELHOUSE: ${{ needs.config.outputs.ovphysx_wheelhouse_image != '' && ((github.event_name == 'pull_request' && github.base_ref == 'develop' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name != 'pull_request' && github.ref_name == 'develop')) }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- name: Resolve OV runtime pins from pyproject
uses: ./.github/actions/resolve-ov-pins
id: ov_pins
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
extra-pip-packages: >-
pytetwild[all]>=0.3.0,<0.4
${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && steps.ov_pins.outputs.ovrtx || format('{0} {1}', steps.ov_pins.outputs.ovrtx, steps.ov_pins.outputs.ovphysx) }}
wheelhouse-image: ${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && needs.config.outputs.ovphysx_wheelhouse_image || '' }}
wheelhouse-packages: ${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && 'ovphysx' || '' }}
include-files: >-
test_rendering_cartpole_kitless.py,
test_rendering_lift_kuka_hetero_kitless.py,
test_rendering_lift_kuka_homo_kitless.py,
test_rendering_franka_cloth_kitless.py,
test_rendering_franka_soft_kitless.py,
test_rendering_franka_cable_kitless.py,
test_rendering_shadow_hand_kitless.py
test-k-expr: legacy
test-node-ids-file: ${{ github.event_name == 'push' && '.github/test-subsets/postmerge-rendering.toml' || '' }}
test-node-ids-key: ${{ github.event_name == 'push' && 'rendering-correctness-kitless-legacy' || '' }}
warp-cache: restore
container-name: "isaac-lab-rendering-correctness-kitless-legacy-test"
omni-github-test-type: "rendering-correctness-kitless-legacy"
# ovstage is post-merge only; it never ran on pull requests.
test-rendering-correctness-kitless-ovstage:
name: "rendering-correctness-kitless (ovstage)"
runs-on: [self-hosted, gpu]
timeout-minutes: 120
continue-on-error: ${{ github.event_name == 'workflow_dispatch' }}
needs: [build, config]
if: >-
github.event_name != 'pull_request' &&
needs.build.result == 'success'
env:
USE_OVPHYSX_WHEELHOUSE: ${{ needs.config.outputs.ovphysx_wheelhouse_image != '' && ((github.event_name == 'pull_request' && github.base_ref == 'develop' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name != 'pull_request' && github.ref_name == 'develop')) }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- name: Resolve OV runtime pins from pyproject
uses: ./.github/actions/resolve-ov-pins
id: ov_pins
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
extra-pip-packages: >-
pytetwild[all]>=0.3.0,<0.4
${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && steps.ov_pins.outputs.ovrtx || format('{0} {1}', steps.ov_pins.outputs.ovrtx, steps.ov_pins.outputs.ovphysx) }}
wheelhouse-image: ${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && needs.config.outputs.ovphysx_wheelhouse_image || '' }}
wheelhouse-packages: ${{ env.USE_OVPHYSX_WHEELHOUSE == 'true' && 'ovphysx' || '' }}
include-files: >-
test_rendering_cartpole_kitless.py,
test_rendering_lift_kuka_hetero_kitless.py,
test_rendering_lift_kuka_homo_kitless.py,
test_rendering_franka_cloth_kitless.py,
test_rendering_franka_soft_kitless.py,
test_rendering_franka_cable_kitless.py,
test_rendering_shadow_hand_kitless.py
test-k-expr: ovstage
test-node-ids-file: ${{ github.event_name == 'push' && '.github/test-subsets/postmerge-rendering.toml' || '' }}
test-node-ids-key: ${{ github.event_name == 'push' && 'rendering-correctness-kitless-ovstage' || '' }}
container-name: "isaac-lab-rendering-correctness-kitless-ovstage-test"
omni-github-test-type: "rendering-correctness-kitless-ovstage"
# Publishes the shared Warp kernel cache the test jobs restore. Needed as its
# own job because a cache written from a PR is readable only by that PR, and
# no solver-heavy test job runs on push. Restores the newest compatible
# snapshot so coverage accumulates, but only publishes when its contents
# change to avoid filling the repository quota with duplicate snapshots.
warm-warp-cache:
name: "warp-cache-warm"
runs-on: [self-hosted, gpu]
timeout-minutes: 180
# A failed warm leaves the previous cache in place, which is a stale cache
# rather than a broken build. Never fail the push build over it.
continue-on-error: true
needs: [build, config]
# One writer per branch. Two concurrent warmers would restore the same
# predecessor, add different kernels, and publish competing successors -
# whichever landed second would silently drop the other's additions.
concurrency:
group: warp-cache-write-${{ github.ref }}
cancel-in-progress: false
if: >-
(github.event_name == 'push' || github.event_name == 'workflow_dispatch') &&
needs.build.result == 'success'
env:
# Caches are branch-scoped: publishing only helps from a PR base branch
# (the on.push.branches list). A dispatch from elsewhere runs as a dry run
# instead of burning quota in a scope no PR can read. Not
# default_branch - that is a release/* branch upstream, excluding main.
PUBLISHES_WARP_CACHE: ${{ github.ref_name == 'main' || github.ref_name == 'develop' || startsWith(github.ref_name, 'release/') }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- uses: ./.github/actions/run-package-tests
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
filter-pattern: "isaaclab_tasks"
# Warm every supported rigid core environment on Newton. MJWarp
# specializes kernels per model config, so a small representative task
# set leaves most of the cache to be compiled again by each PR test
# shard. The multi-agent suite supplies Handover.
include-files: >-
test_environments_newton.py,
test_multi_agent_environments.py
# Deformable tasks need optional dependencies that are not installed in
# this image.
test-k-expr: "test_environments and not (Soft or Cloth or Cable)"
warp-cache: ${{ env.PUBLISHES_WARP_CACHE == 'true' && 'save' || 'restore' }}
container-name: isaac-lab-warp-cache-warm
omni-github-test-type: warp-cache-warm
#endregion
#region disabled quarantined tests
# test-quarantined:
# name: "Quarantined Tests"
# runs-on: [self-hosted, gpu]
# timeout-minutes: 180
# continue-on-error: true
# needs: [build, config]
# if: >-
# needs.build.result == 'success' &&
# vars.RUN_QUARANTINED_TESTS == 'true'
# steps:
# - uses: actions/checkout@v6
# with:
# fetch-depth: 1
# lfs: true
# - uses: ./.github/actions/run-package-tests
# with:
# image-tag: ${{ needs.config.outputs.ci_image_tag }}
# isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
# isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
# quarantined-only: "true"
# container-name: isaac-lab-quarantined-test
#endregion