Skip to content

Fixes Newton cloner ignoring collision approximation #12967

Fixes Newton cloner ignoring collision approximation

Fixes Newton cloner ignoring collision approximation #12967

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
name: Python Dependency Licenses Check
on:
pull_request:
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
license-check:
# Fork PRs cannot access NGC_API_KEY, so they cannot resolve the immutable
# OVPhysX wheel required by the development extras.
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-24.04
env:
NGC_API_KEY: ${{ secrets.NGC_API_KEY }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
filter: tree:0
- name: Load OVPhysX wheelhouse configuration
id: config
shell: bash
run: |
set -euo pipefail
resource=$(yq -r .ovphysx_wheelhouse_resource .github/workflows/config.yaml)
echo "wheelhouse_resource=${resource}" >> "$GITHUB_OUTPUT"
- name: Restore NGC CLI cache
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/ngc-cli-cache/ngccli_linux.zip
key: ngc-cli-${{ runner.os }}-${{ runner.arch }}-4.20.0-5cf084c88998c58ad8abf7849d2d1b41d578423886eb03018df10194e341d35b
- name: Extract OVPhysX wheelhouse
id: extract-wheelhouse
shell: bash
env:
WHEELHOUSE_RESOURCE: ${{ steps.config.outputs.wheelhouse_resource }}
run: |
set -euo pipefail
if [ -z "${NGC_API_KEY:-}" ]; then
echo "::error::NGC_API_KEY is unavailable; cannot download the configured OVPhysX wheelhouse"
exit 1
fi
NGC_CLI_VERSION="4.20.0"
NGC_CLI_SHA256="5cf084c88998c58ad8abf7849d2d1b41d578423886eb03018df10194e341d35b"
NGC_CLI_URL="https://api.ngc.nvidia.com/v2/resources/nvidia/ngc-apps/ngc_cli/versions/${NGC_CLI_VERSION}/files/ngccli_linux.zip"
wheelhouse_root="$(mktemp -d "${RUNNER_TEMP:-/tmp}/ovphysx-wheelhouse.XXXXXX")"
download_root="$(mktemp -d "${RUNNER_TEMP:-/tmp}/ovphysx-wheelhouse-download.XXXXXX")"
ngc_home="$(mktemp -d "${RUNNER_TEMP:-/tmp}/ovphysx-ngc-home.XXXXXX")"
ngc_unpack_dir=""
preserve_wheelhouse_root=false
cleanup() {
if [ "$preserve_wheelhouse_root" != "true" ]; then
rm -rf "$wheelhouse_root"
fi
rm -rf "$download_root" "$ngc_home"
if [ -n "$ngc_unpack_dir" ]; then
rm -rf "$ngc_unpack_dir"
fi
}
trap cleanup EXIT
cache_dir="${RUNNER_TEMP:-/tmp}/ngc-cli-cache"
ngc_zip="${cache_dir}/ngccli_linux.zip"
mkdir -p "$cache_dir"
if [ ! -f "$ngc_zip" ]; then
echo "Downloading NGC CLI ${NGC_CLI_VERSION}"
curl -fsSL -o "$ngc_zip" "$NGC_CLI_URL"
fi
echo "${NGC_CLI_SHA256} ${ngc_zip}" | sha256sum -c -
ngc_unpack_dir="$(mktemp -d "${RUNNER_TEMP:-/tmp}/ngc-cli.XXXXXX")"
unzip -q "$ngc_zip" -d "$ngc_unpack_dir"
export PATH="${ngc_unpack_dir}/ngc-cli:${PATH}"
export NGC_CLI_API_KEY="$NGC_API_KEY"
export NGC_CLI_ORG=nvidian
export NGC_CLI_TEAM=no-team
export NGC_CLI_HOME="$ngc_home"
ngc --version
echo "Downloading wheelhouse resource: $WHEELHOUSE_RESOURCE"
ngc registry resource download-version "$WHEELHOUSE_RESOURCE" --dest "$download_root"
mapfile -t manifests < <(find "$download_root" -type f -name manifest.json)
if [ "${#manifests[@]}" -ne 1 ]; then
echo "::error::expected exactly one manifest.json in downloaded wheelhouse resource, found ${#manifests[@]}"
printf '%s\n' "${manifests[@]}"
exit 1
fi
payload_dir="$(dirname "${manifests[0]}")"
if [ ! -d "${payload_dir}/wheelhouse" ]; then
echo "::error::downloaded wheelhouse resource is missing wheelhouse/ next to manifest.json"
exit 1
fi
mkdir -p "$wheelhouse_root/wheelhouse"
cp "${payload_dir}/manifest.json" "$wheelhouse_root/manifest.json"
cp "${payload_dir}/wheelhouse/"*.whl "$wheelhouse_root/wheelhouse/"
python3 - <<'PY' "$wheelhouse_root/manifest.json" "$wheelhouse_root/wheelhouse"
import hashlib
import json
import pathlib
import sys
manifest_path = pathlib.Path(sys.argv[1])
wheelhouse_dir = pathlib.Path(sys.argv[2])
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
expected = {
"artifact": "ovphysx-wheelhouse",
"platform": "manylinux_2_35_x86_64",
}
for key, value in expected.items():
actual = manifest.get(key)
if actual != value:
raise SystemExit(f"manifest {key!r} mismatch: expected {value!r}, got {actual!r}")
wheels = manifest.get("wheels")
if not isinstance(wheels, list) or not wheels:
raise SystemExit("manifest has no wheels list")
for wheel in wheels:
filename = wheel.get("file")
expected_sha = wheel.get("sha256")
if not filename or not expected_sha:
raise SystemExit(f"invalid wheel manifest entry: {wheel!r}")
wheel_path = wheelhouse_dir / filename
if not wheel_path.is_file():
raise SystemExit(f"manifest wheel is missing from wheelhouse: {filename}")
actual_sha = hashlib.sha256(wheel_path.read_bytes()).hexdigest()
if actual_sha != expected_sha:
raise SystemExit(f"sha256 mismatch for {filename}: expected {expected_sha}, got {actual_sha}")
print(f"Validated {len(wheels)} wheelhouse wheels from {manifest_path}")
PY
echo "wheelhouse_root=$wheelhouse_root" >> "$GITHUB_OUTPUT"
echo "wheelhouse_dir=$wheelhouse_root/wheelhouse" >> "$GITHUB_OUTPUT"
# - name: Install jq
# run: sudo apt-get update && sudo apt-get install -y jq
- name: Clean up disk space
run: |
# Remove pre-installed tools
rm -rf /opt/hostedtoolcache
rm -rf /usr/share/dotnet
rm -rf /opt/ghc
sudo rm -rf /usr/local/lib/android
rm -rf /usr/share/swift
rm -rf /usr/local/share/boost
sudo rm -rf /usr/local/.ghcup
sudo rm -rf /usr/local/lib/node_modules
sudo rm -rf /usr/local/share/chromium
sudo rm -rf /usr/local/share/powershell
# Clean apt cache
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
# Docker cleanup
docker container prune -f
docker image prune -af
docker volume prune -f
docker system prune -af
- name: Set up uv
uses: astral-sh/setup-uv@v6
with:
python-version: '3.12'
enable-cache: true
- name: Install dependencies with uv
env:
OMNI_KIT_ACCEPT_EULA: yes
ACCEPT_EULA: Y
ISAACSIM_ACCEPT_EULA: YES
UV_FIND_LINKS: ${{ steps.extract-wheelhouse.outputs.wheelhouse_dir }}
run: |
uv sync --extra all
# Isaac Sim conflicts with --extra all under uv, so install it imperatively
# after the sync. Read the pinned spec from pyproject (single source of truth).
ISAACSIM_SPEC=$(.venv/bin/python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['optional-dependencies']['isaacsim'][0])")
uv pip install "$ISAACSIM_SPEC"
uv pip install pip-licenses pipdeptree \
-r tools/template/requirements.txt \
-r docs/requirements.txt
# Put the venv on PATH for later steps.
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
# Optional: Print the license report for visibility
- name: Print License Report
run: pip-licenses --from=mixed --format=markdown
# Print pipdeptree
- name: Print pipdeptree
run: pipdeptree
- name: Check licenses against whitelist and exceptions
run: |
# Define the whitelist of allowed licenses
ALLOWED_LICENSES="MIT Apache BSD ISC zlib"
# Load the exceptions list from the exceptions.json file
EXCEPTIONS_FILE=".github/workflows/license-exceptions.json"
# Initialize counter for failed packages
FAILED_PACKAGES=0
# Get the list of installed packages and their licenses
pip-licenses --from=mixed --format=json > licenses.json
# Check the output of pip-licenses to ensure it is valid JSON
if ! jq empty licenses.json; then
echo "ERROR: Failed to parse pip-licenses output. Exiting..."
exit 1
fi
# Split ALLOWED_LICENSES into individual words
IFS=' ' read -r -a allowed_licenses <<< "$ALLOWED_LICENSES"
# Loop through the installed packages and their licenses
for pkg in $(jq -r '.[].Name' licenses.json); do
# Skip packages starting with nvidia (case-insensitive)
if [[ "${pkg,,}" == nvidia* ]]; then
continue
fi
LICENSE=$(jq -r --arg pkg "$pkg" '.[] | select(.Name == $pkg) | .License' licenses.json)
# Check if any of the allowed licenses are a substring of the package's license
match_found=false
for allowed_license in "${allowed_licenses[@]}"; do
if [[ "$LICENSE" == *"$allowed_license"* ]]; then
match_found=true
break
fi
done
if [ "$match_found" = false ]; then
# Check if the package is in the exceptions list
EXCEPTION=$(jq -r --arg pkg "$pkg" --arg license "$LICENSE" \
'.[] | select(.package == $pkg)' "$EXCEPTIONS_FILE")
# If the package is in the exceptions list
if [ -n "$EXCEPTION" ]; then
# If the license is provided in the exceptions list, check the license
EXCEPTION_LICENSE=$(echo "$EXCEPTION" | jq -r '.license')
# echo "Comparing licenses for $pkg:"
# echo " EXCEPTION_LICENSE='${EXCEPTION_LICENSE}' (len=${#EXCEPTION_LICENSE})"
# echo " LICENSE='${LICENSE}' (len=${#LICENSE})"
# If the exceptions list has a license and doesn't match the current license
if [ "$EXCEPTION_LICENSE" != "null" ] && [ "$EXCEPTION_LICENSE" != "$LICENSE" ]; then
echo "ERROR: $pkg has license: $LICENSE"
FAILED_PACKAGES=$((FAILED_PACKAGES + 1)) # Increment the counter
fi
else
# If the package is not in the exceptions list
echo "ERROR: $pkg has license: $LICENSE"
FAILED_PACKAGES=$((FAILED_PACKAGES + 1)) # Increment the counter
fi
fi
done
# After all packages are processed, check if there were any errors
if [ "$FAILED_PACKAGES" -gt 0 ]; then
echo "ERROR: $FAILED_PACKAGES packages were flagged."
exit 1 # Fail the build
else
echo "All packages were checked."
fi
- name: Clean up OVPhysX wheelhouse
if: always()
shell: bash
run: |
rm -rf "${{ steps.extract-wheelhouse.outputs.wheelhouse_root }}"