Record measured noise floors next to the thresholds #11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). | ||
|
Check failure on line 1 in .github/workflows/build.yaml
|
||
| # 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 | ||
| ^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_" | ||
| 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_" | ||
| 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_" | ||
| 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 | ||
| test-standalone-demos: | ||
| name: standalone demos (headless, ${{ matrix.runtime-label }}) | ||
| runs-on: [self-hosted, gpu] | ||
| timeout-minutes: 180 | ||
| needs: [build, config] | ||
| if: >- | ||
| github.event_name != 'push' && | ||
| needs.build.result == 'success' | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - runtime-group: kit | ||
| runtime-label: Kit | ||
| - runtime-group: non-kit | ||
| runtime-label: non-Kit | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 1 | ||
| lfs: true | ||
| - name: Resolve OVPhysX runtime pin from pyproject | ||
| if: matrix.runtime-group == 'non-kit' | ||
| 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: ${{ matrix.runtime-group }} | ||
| result-file: "test-standalone-demos-${{ matrix.runtime-group }}-report.xml" | ||
| container-name: isaac-lab-standalone-demos-${{ matrix.runtime-group }}-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-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-skillgen: | ||
| name: test-skillgen | ||
| 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_environments_skillgen.py,test_environments_automate.py" | ||
| container-name: isaac-lab-skillgen-test | ||
| test-environments-training: | ||
| name: "environments_training" | ||
| runs-on: [self-hosted, gpu] | ||
| timeout-minutes: 300 | ||
| 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_environments_training.py" | ||
| container-name: isaac-lab-environments-training-test | ||
| omni-github-test-type: training-e2e | ||
| 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_record_video.py" | ||
| test-k-expr: "Cartpole" | ||
| 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_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' || '' }} | ||
| container-name: isaac-lab-rendering-correctness-test | ||
| omni-github-test-type: rendering-correctness | ||
| test-rendering-correctness-kitless: | ||
| name: "rendering-correctness-kitless (${{ matrix.variant }})" | ||
| runs-on: [self-hosted, gpu] | ||
| timeout-minutes: 120 | ||
| continue-on-error: ${{ github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && matrix.variant == 'ovstage') }} | ||
| needs: [build, config] | ||
| if: needs.build.result == 'success' | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| variant: [legacy, ovstage] | ||
| event_name: | ||
| - ${{ github.event_name }} | ||
| exclude: | ||
| - variant: ovstage | ||
| event_name: pull_request | ||
| 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_shadow_hand_kitless.py | ||
| test-k-expr: ${{ matrix.variant }} | ||
| test-node-ids-file: ${{ github.event_name == 'push' && '.github/test-subsets/postmerge-rendering.toml' || '' }} | ||
| test-node-ids-key: ${{ github.event_name == 'push' && format('rendering-correctness-kitless-{0}', matrix.variant) || '' }} | ||
| container-name: "isaac-lab-rendering-correctness-kitless-${{ matrix.variant }}-test" | ||
| omni-github-test-type: "rendering-correctness-kitless-${{ matrix.variant }}" | ||
| performance-smoke: | ||
| name: "performance-smoke (${{ matrix.name }})" | ||
| runs-on: [self-hosted, gpu] | ||
| # Budget for two attempts plus image pull and cache restore. | ||
| # Each attempt is bounded individually by `timeout` to prevent starving retry. | ||
| timeout-minutes: ${{ matrix.timeout_minutes * 2 + 10 }} | ||
| needs: [build, config] | ||
| # Pull requests run in gate mode, pushes to develop additionally record baseline. | ||
| if: >- | ||
| (github.event_name != 'push' || github.ref == 'refs/heads/develop') && | ||
| needs.build.result == 'success' | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - name: cartpole-physx | ||
| task: Isaac-Cartpole-Direct | ||
| num_envs: 4096 | ||
| timeout_minutes: 10 | ||
| args: "" | ||
| - name: cartpole-newton | ||
| task: Isaac-Cartpole-Direct | ||
| num_envs: 4096 | ||
| timeout_minutes: 10 | ||
| args: physics=newton_mjwarp | ||
| - name: gear-mesh-physx | ||
| task: IsaacContrib-Factory-GearMesh-Direct | ||
| num_envs: 512 | ||
| timeout_minutes: 15 | ||
| args: "" | ||
| - name: shadow-camera-physx-rtx | ||
| task: Isaac-Reorient-Cube-Shadow-Camera-Benchmark-Direct | ||
| num_envs: 512 | ||
| timeout_minutes: 20 | ||
| args: renderer=isaacsim_rtx | ||
| - name: shadow-camera-physx-newton-renderer | ||
| task: Isaac-Reorient-Cube-Shadow-Camera-Benchmark-Direct | ||
| num_envs: 512 | ||
| timeout_minutes: 20 | ||
| args: renderer=newton_renderer | ||
| - name: shadow-camera-newton-rtx | ||
| task: Isaac-Reorient-Cube-Shadow-Camera-Benchmark-Direct | ||
| num_envs: 512 | ||
| timeout_minutes: 20 | ||
| args: physics=newton_mjwarp renderer=isaacsim_rtx | ||
| - name: shadow-camera-newton-renderer | ||
| task: Isaac-Reorient-Cube-Shadow-Camera-Benchmark-Direct | ||
| num_envs: 512 | ||
| timeout_minutes: 20 | ||
| args: physics=newton_mjwarp renderer=newton_renderer | ||
| - name: g1-physx | ||
| task: Isaac-Velocity-Flat-G1 | ||
| num_envs: 512 | ||
| timeout_minutes: 12 | ||
| args: "" | ||
| - name: g1-newton | ||
| task: Isaac-Velocity-Flat-G1 | ||
| num_envs: 512 | ||
| timeout_minutes: 12 | ||
| args: physics=newton_mjwarp | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 1 | ||
| - name: Pull pull-request image | ||
| 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 | ||
| - name: Resolve Warp version for the JIT cache key | ||
| id: warp_version | ||
| run: | | ||
| set -euo pipefail | ||
| version="$(sed -n 's/.*warp-lang[^0-9]*\([0-9][0-9A-Za-z.\-]*\).*/\1/p' pyproject.toml | head -n1)" | ||
| if [ -z "$version" ]; then | ||
| echo "::error::Could not resolve the warp-lang pin from pyproject.toml; the JIT cache key would stop tracking Warp" | ||
| exit 1 | ||
| fi | ||
| echo "value=$version" >> "$GITHUB_OUTPUT" | ||
| - name: Restore warm JIT cache | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ${{ github.workspace }}/jit-cache | ||
| key: perf-jit-warp${{ steps.warp_version.outputs.value }}-${{ matrix.name }}-${{ github.run_id }} | ||
| restore-keys: | | ||
| perf-jit-warp${{ steps.warp_version.outputs.value }}-${{ matrix.name }}- | ||
| perf-jit-warp${{ steps.warp_version.outputs.value }}- | ||
| - name: Run runtime benchmark | ||
| env: | ||
| BENCHMARK_ARGS: ${{ matrix.args }} | ||
| BENCHMARK_TASK: ${{ matrix.task }} | ||
| CI_IMAGE_TAG: ${{ needs.config.outputs.ci_image_tag }} | ||
| NUM_ENVS: ${{ matrix.num_envs }} | ||
| BENCH_TIMEOUT_S: ${{ matrix.timeout_minutes * 60 }} | ||
| run: | | ||
| set -uo pipefail | ||
| install -d -m 0777 benchmark-output | ||
| # World-writable so the in-container user (uid 1000) can populate the cache | ||
| install -d -m 0777 "${GITHUB_WORKSPACE}/jit-cache/warp" "${GITHUB_WORKSPACE}/jit-cache/nv" | ||
| run_attempt() { | ||
| local attempt="$1" | ||
| local container="performance-smoke-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.name }}-${attempt}" | ||
| docker rm -f "$container" >/dev/null 2>&1 || true | ||
| timeout "${BENCH_TIMEOUT_S}" docker run --name "$container" --gpus all --network=host --ipc=host \ | ||
| -e OMNI_KIT_ACCEPT_EULA=yes \ | ||
| -e ACCEPT_EULA=Y \ | ||
| -e ISAAC_SIM_HEADLESS=1 \ | ||
| -e WARP_CACHE_PATH=/tmp/jit-cache/warp \ | ||
| -e CUDA_CACHE_PATH=/tmp/jit-cache/nv \ | ||
| -v "${GITHUB_WORKSPACE}/jit-cache:/tmp/jit-cache" \ | ||
| --entrypoint bash "$CI_IMAGE_TAG" -lc \ | ||
| "set -euo pipefail | ||
| mkdir -p /tmp/benchmark-output | ||
| ./isaaclab.sh benchmark runtime \ | ||
| --task '$BENCHMARK_TASK' \ | ||
| --num_envs '$NUM_ENVS' \ | ||
| --num_steps 200 \ | ||
| --warmup_steps 100 \ | ||
| --seed 42 \ | ||
| --benchmark_formatter schema \ | ||
| --output_path /tmp/benchmark-output \ | ||
| --visualizer none \ | ||
| $BENCHMARK_ARGS" | ||
| local status=$? | ||
| docker cp "$container:/tmp/benchmark-output/." benchmark-output/ 2>/dev/null || true | ||
| docker rm -f "$container" >/dev/null 2>&1 || true | ||
| return $status | ||
| } | ||
| if ! run_attempt 1; then | ||
| echo "::warning::${{ matrix.name }} failed on the first attempt; retrying once" | ||
| rm -f benchmark-output/benchmark_runtime_*.json | ||
| run_attempt 2 | ||
| fi | ||
| # Read-only. Recording step below is the only writer scoped to refs/heads/develop. | ||
| - name: Compare against baseline history | ||
| env: | ||
| PERF_BASELINE_URI: ${{ vars.PERF_BASELINE_URI }} | ||
| run: | | ||
| set -euo pipefail | ||
| mapfile -t results < <(find benchmark-output -maxdepth 1 -type f -name 'benchmark_runtime_*.json') | ||
| if [ "${#results[@]}" -ne 1 ]; then | ||
| echo "::error::Expected one runtime benchmark JSON, found ${#results[@]}" | ||
| exit 1 | ||
| fi | ||
| # An unset URI yields SKIP, not failure because a missing baseline is not a regression. | ||
| python3 -m tools.perf_smoke.cli compare \ | ||
| --benchmark_result "${results[0]}" \ | ||
| --baseline_uri "${PERF_BASELINE_URI:-}" \ | ||
| --label "${{ matrix.name }}" \ | ||
| --output_json benchmark-output/comparison.json \ | ||
| | tee -a "$GITHUB_STEP_SUMMARY" | ||
| # Only develop records baselines, so the gate always compares a pull request | ||
| # against the branch it will merge into rather than against a stale snapshot. | ||
| - name: Record baseline | ||
| if: ${{ github.ref == 'refs/heads/develop' && vars.PERF_BASELINE_URI != '' }} | ||
| env: | ||
| PERF_BASELINE_URI: ${{ vars.PERF_BASELINE_URI }} | ||
| run: | | ||
| set -euo pipefail | ||
| mapfile -t results < <(find benchmark-output -maxdepth 1 -type f -name 'benchmark_runtime_*.json') | ||
| python3 -m tools.perf_smoke.cli write \ | ||
| --benchmark_result "${results[0]}" \ | ||
| --baseline_uri "$PERF_BASELINE_URI" \ | ||
| --commit "$GITHUB_SHA" \ | ||
| --timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ | ||
| --run_id "$GITHUB_RUN_ID" | ||
| - name: Upload performance results | ||
| if: always() | ||
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: performance-smoke-${{ matrix.name }}-${{ github.run_id }} | ||
| path: benchmark-output/ | ||
| if-no-files-found: warn | ||
| retention-days: 7 | ||
| # Centralized summary; individual failed tasks still display their own failed jobs. | ||
| performance-smoke-summary: | ||
| name: performance-smoke | ||
| runs-on: ubuntu-latest | ||
| needs: [performance-smoke] | ||
| if: always() && needs.performance-smoke.result != 'skipped' | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 1 | ||
| - uses: actions/download-artifact@v7 | ||
| with: | ||
| pattern: performance-smoke-*-${{ github.run_id }} | ||
| path: comparisons | ||
| continue-on-error: true | ||
| - name: Summarise performance comparisons | ||
| run: | | ||
| set -euo pipefail | ||
| python3 -m tools.perf_smoke.cli aggregate \ | ||
| --comparison_dir comparisons \ | ||
| | tee -a "$GITHUB_STEP_SUMMARY" | ||
| # 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. Does not restore before saving: | ||
| # appending to the previous run grows the cache without bound, which is what | ||
| # exhausted the repository quota last time. | ||
| 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" | ||
| # MJWarp specializes kernels per model config (@cache_kernel in | ||
| # mujoco_warp/_src/warp_util.py keys on array sizes; ~250 wp.static uses | ||
| # feed Warp's module hash), so these span specialization axes rather than | ||
| # maximize task count: Cartpole (primitives, contact-free, + camera), | ||
| # Drawer (mesh collision), AnymalD (contact-rich locomotion), Handover | ||
| # (dexterous, many contacts). Deformable/MPM kernels are not covered; | ||
| # widen if a test job reports large cache growth. | ||
| include-files: >- | ||
| test_environments.py, | ||
| test_environments_newton.py | ||
| # No Soft/Cloth: the deformable envs depend on optional extras the CI | ||
| # image does not install (Soft needs pytetwild), so they only ever fail. | ||
| test-k-expr: "Cartpole or Drawer or AnymalD or Handover" | ||
| 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 | ||