Skip to content

feat(training): add NVIDIA ARM64 support for LeRobot 0.6.1 #3827

feat(training): add NVIDIA ARM64 support for LeRobot 0.6.1

feat(training): add NVIDIA ARM64 support for LeRobot 0.6.1 #3827

Workflow file for this run

name: PR Validation
on:
pull_request:
branches:
- main
types:
- opened
- synchronize
- reopened
permissions:
contents: read
jobs:
# Detect changed paths to gate expensive test jobs
changes:
name: Detect Changes
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
training: ${{ steps.filter.outputs.training }}
rl: ${{ steps.filter.outputs.rl }}
il: ${{ steps.filter.outputs.il }}
dm_tools: ${{ steps.filter.outputs.dm_tools }}
data_pipeline: ${{ steps.filter.outputs.data_pipeline }}
inference: ${{ steps.filter.outputs.inference }}
shared_ci: ${{ steps.filter.outputs.shared_ci }}
dv_backend: ${{ steps.filter.outputs.dv_backend }}
dv_frontend: ${{ steps.filter.outputs.dv_frontend }}
fuzz: ${{ steps.filter.outputs.fuzz }}
docusaurus: ${{ steps.filter.outputs.docusaurus }}
pester: ${{ steps.filter.outputs.pester }}
containers: ${{ steps.filter.outputs.containers }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Compute path filters
id: filter
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail
FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
echo "Changed files:"
echo "$FILES"
# match() returns false (not an error) on an empty/non-matching diff.
# That is safe: the unconditional CPU import baseline in smoke-cpu.yml
# runs regardless of these outputs, so a false here can only narrow the
# path-gated runtime-image depth, never silently skip the gate.
match() { echo "$FILES" | grep -qE "$1" && echo true || echo false; }
pester_match=$(match '\.(ps1|psm1|psd1)$')
echo "Computed pester=$pester_match"
{
echo "training=$(match '^training/')"
echo "rl=$(match '^(training/rl/|shared/ci/|scripts/lib/common\.sh|\.github/workflows/smoke-cpu\.yml)')"
echo "il=$(match '^(training/il/|shared/ci/|\.github/workflows/smoke-cpu\.yml)')"
echo "dm_tools=$(match '^data-management/tools/')"
echo "data_pipeline=$(match '^data-pipeline/capture/')"
echo "inference=$(match '^fleet-deployment/inference/')"
echo "shared_ci=$(match '^shared/ci/')"
echo "dv_backend=$(match '^(data-management/viewer/backend/|data-management/viewer/docker-compose\.yml|shared/ci/smoke-docker\.sh|\.github/workflows/smoke-cpu\.yml)')"
echo "dv_frontend=$(match '^data-management/viewer/frontend/')"
echo "fuzz=$(match '^(tests/fuzz|tests/fuzz_harness\.py|tests/generate_fuzz_corpus\.py|data-management/viewer/backend/src/|training/)')"
echo "docusaurus=$(match '^docs/docusaurus/')"
echo "pester=$pester_match"
echo "containers=$(match '(Dockerfile|^\.github/workflows/container-scan\.yml$|^scripts/security/(discover-base-images|image-slug)\.sh$)')"
} >> "$GITHUB_OUTPUT"
# GPU-free import smoke gate. CPU import smoke runs for every domain on every
# PR (unconditional baseline); the runtime-image smoke is path-gated to the
# changed training domain.
smoke:
name: Smoke
needs: changes
uses: ./.github/workflows/smoke-cpu.yml
with:
rl: ${{ needs.changes.outputs.rl == 'true' }}
il: ${{ needs.changes.outputs.il == 'true' }}
dataviewer: ${{ needs.changes.outputs.dv_backend == 'true' || needs.changes.outputs.dv_frontend == 'true' }}
permissions:
contents: read
# Validate that all `uses: ./.github/workflows/*.yml` references resolve
workflow-refs-check:
name: Workflow Refs Check
uses: ./.github/workflows/workflow-refs-check.yml
permissions:
contents: read
# Spell checking using cspell
spell-check:
name: Spell Check
uses: ./.github/workflows/spell-check.yml
permissions:
contents: read
# Markdown linting using markdownlint-cli2
markdown-lint:
name: Markdown Lint
uses: ./.github/workflows/markdown-lint.yml
permissions:
contents: read
# Markdown table formatting check
table-format:
name: Table Format
uses: ./.github/workflows/table-format.yml
permissions:
contents: read
# Frontmatter validation for markdown files
frontmatter-validation:
name: Frontmatter Validation
uses: ./.github/workflows/frontmatter-validation.yml
with:
changed-files-only: true
permissions:
contents: read
# ms.date Freshness Check
msdate-freshness:
name: ms.date Freshness Check
uses: ./.github/workflows/msdate-freshness-check.yml
with:
staleness-threshold-days: 90
changed-files-only: true
soft-fail: false
permissions:
contents: read
# PowerShell script analysis
psscriptanalyzer:
name: PSScriptAnalyzer
uses: ./.github/workflows/ps-script-analyzer.yml
with:
changed-files-only: true
permissions:
contents: read
# YAML/actionlint workflow linting
yaml-lint:
name: YAML Lint
uses: ./.github/workflows/yaml-lint.yml
with:
changed-files-only: true
permissions:
contents: read
# Link language locale check
link-lang-check:
name: Link Language Check
uses: ./.github/workflows/link-lang-check.yml
permissions:
contents: read
# Markdown link validation
markdown-link-check:
name: Markdown Link Check
uses: ./.github/workflows/markdown-link-check.yml
permissions:
contents: read
# Dependency review for security vulnerabilities
dependency-review:
name: Dependency Review
uses: ./.github/workflows/dependency-review.yml
permissions:
contents: read
pull-requests: write
# SHA pinning compliance for GitHub Actions and dependencies
dependency-pinning:
name: Dependency Pinning
uses: ./.github/workflows/dependency-pinning-scan.yml
permissions:
contents: read
security-events: write # Required for SARIF upload to Security tab
with:
upload-sarif: true
exclude-paths: 'scripts/tests/Fixtures/**,shared/ci/tests/Fixtures/**'
# OSV-Scanner: advisory-only vulnerability scan across manifests using
# osv-scanner.toml. The scan step uses continue-on-error so the job always
# reports success (green) even when vulnerabilities are found; findings still
# surface in the Security tab via SARIF. This job is intentionally excluded
# from the pr-validation-summary gate.
osv-scanner:
name: OSV-Scanner
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # Required for SARIF upload to Security tab
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run OSV-Scanner
uses: google/osv-scanner-action/osv-scanner-action@6e4298ebc4db23e847df9b2e2de2939d6f066c67 # v2.5.1
continue-on-error: true
with:
# --no-resolve disables transitive resolution; pinned requirements files
# contain version pins that conflict with transitive constraints, but
# every pinned package is still scanned directly.
scan-args: |-
--config=osv-scanner.toml
--no-resolve
--recursive
./
# Container base-image CVE scan (Trivy). Discovers every digest-pinned base
# image across the repo's Dockerfiles and reports fixable CRITICAL/HIGH
# vulnerabilities to the Security tab. Runs soft-fail while the shipped base
# images still carry fixable CVEs (see #1085). Path-gated to Dockerfile, scan
# workflow, or discovery/slug helper changes; a weekly Container Rescan
# re-evaluates already-merged base images.
container-scan:
name: Container Scan
needs: changes
if: needs.changes.outputs.containers == 'true'
uses: ./.github/workflows/container-scan.yml
with:
soft-fail: true
permissions:
contents: read
security-events: write # Required for SARIF upload to Security tab
# PowerShell Pester test execution
pester-tests:
name: Pester Tests
needs: changes
if: needs.changes.outputs.pester == 'true'
uses: ./.github/workflows/pester-tests.yml
with:
code-coverage: true
changed-files-only: false
soft-fail: false
permissions:
contents: read
id-token: write
# Dataviewer frontend lint, type-check, and unit tests
dataviewer-frontend-tests:
name: Dataviewer Frontend Tests
needs: changes
if: needs.changes.outputs.dv_frontend == 'true'
uses: ./.github/workflows/dataviewer-frontend-tests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Docusaurus documentation site tests and build verification
docusaurus-tests:
name: Docusaurus Tests
needs: changes
if: needs.changes.outputs.docusaurus == 'true'
uses: ./.github/workflows/docusaurus-tests.yml
with:
soft-fail: false
permissions:
contents: read
# Pytest: training component
pytest-training:
name: Pytest Training
needs: changes
if: needs.changes.outputs.training == 'true'
uses: ./.github/workflows/pytest-training.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: data-management/tools component
pytest-dm-tools:
name: Pytest DM Tools
needs: changes
if: needs.changes.outputs.dm_tools == 'true'
uses: ./.github/workflows/pytest-dm-tools.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: data-pipeline component
pytest-data-pipeline:
name: Pytest Data Pipeline
needs: changes
if: needs.changes.outputs.data_pipeline == 'true'
uses: ./.github/workflows/pytest-data-pipeline.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: inference component
pytest-inference:
name: Pytest Inference
needs: changes
if: needs.changes.outputs.inference == 'true'
uses: ./.github/workflows/pytest-inference.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: shared CI scripts component
pytest-shared-ci:
name: Pytest Shared CI
needs: changes
if: needs.changes.outputs.shared_ci == 'true'
uses: ./.github/workflows/pytest-shared-ci.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Dataviewer backend pytest execution
dataviewer-backend-pytests:
name: Dataviewer Backend Pytest
needs: changes
if: needs.changes.outputs.dv_backend == 'true'
uses: ./.github/workflows/dataviewer-backend-pytests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Evaluation domain pytest execution
evaluation-pytests:
name: Evaluation Pytest
uses: ./.github/workflows/evaluation-pytests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Fuzz regression via deterministic corpus-based tests
fuzz-regression-tests:
name: Fuzz Regression Tests
needs: changes
if: needs.changes.outputs.fuzz == 'true'
uses: ./.github/workflows/fuzz-regression-tests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Python linting using ruff
python-lint:
name: Python Lint
uses: ./.github/workflows/python-lint.yml
permissions:
contents: read
# uv lock/manifest consistency gate across all Python subprojects
uv-lock-consistency:
name: uv Lock Consistency
uses: ./.github/workflows/uv-lock-consistency.yml
with:
changed-files-only: true
soft-fail: false
permissions:
contents: read
# Terraform linting using TFLint
terraform-lint:
name: Terraform Lint
uses: ./.github/workflows/terraform-lint.yml
with:
soft-fail: false
permissions:
contents: read
# Terraform format and validate checks
terraform-validation:
name: Terraform Validation
uses: ./.github/workflows/terraform-validation.yml
with:
soft-fail: false
changed-files-only: true
permissions:
contents: read
# Terraform security scanning via Checkov (soft-fail until matrix is fully addressed)
terraform-security:
name: Terraform Security
uses: ./.github/workflows/terraform-security.yml
with:
soft-fail: true
working-directory: infrastructure/terraform
permissions:
contents: read
security-events: write
# Terraform test execution with Codecov Test Analytics
terraform-tests:
name: Terraform Tests
uses: ./.github/workflows/terraform-tests.yml
with:
soft-fail: true
changed-files-only: true
code-coverage: true
permissions:
contents: read
id-token: write
# Go linting using golangci-lint
go-lint:
name: Go Lint
uses: ./.github/workflows/go-lint.yml
with:
soft-fail: false
changed-files-only: true
permissions:
contents: read
# Terraform documentation freshness check
terraform-docs-check:
name: Terraform Docs Check
uses: ./.github/workflows/terraform-docs-check.yml
with:
soft-fail: true
changed-files-only: true
permissions:
contents: read
# Go tests
go-tests:
name: Go Tests
uses: ./.github/workflows/go-tests.yml
with:
soft-fail: false
code-coverage: true
permissions:
contents: read
id-token: write
# ShellCheck linting for shell scripts
shellcheck:
name: ShellCheck
uses: ./.github/workflows/shellcheck.yml
with:
soft-fail: false
changed-files-only: true
permissions:
contents: read
# CodeQL security analysis
codeql-analysis:
name: CodeQL Analysis
uses: ./.github/workflows/codeql-analysis.yml
permissions:
contents: read
security-events: write
actions: read
# Single required-status-check aggregator. Set this as the sole required
# check in branch protection. Skipped jobs (gated out by changes) pass;
# any failure or cancellation in a needed job fails the summary.
pr-validation-summary:
if: always()
runs-on: ubuntu-latest
needs:
- changes
- workflow-refs-check
- spell-check
- markdown-lint
- table-format
- frontmatter-validation
- msdate-freshness
- psscriptanalyzer
- yaml-lint
- link-lang-check
- markdown-link-check
- dependency-review
- dependency-pinning
- pester-tests
- dataviewer-frontend-tests
- docusaurus-tests
- pytest-training
- pytest-dm-tools
- pytest-data-pipeline
- pytest-inference
- pytest-shared-ci
- dataviewer-backend-pytests
- evaluation-pytests
- fuzz-regression-tests
- python-lint
- uv-lock-consistency
- terraform-lint
- terraform-validation
- terraform-tests
- go-lint
- terraform-docs-check
- go-tests
- shellcheck
- codeql-analysis
- smoke
- container-scan
permissions:
contents: read
steps:
- name: Evaluate needed job results
env:
NEEDS_JSON: ${{ toJSON(needs) }}
run: |
set -euo pipefail
echo "$NEEDS_JSON"
failed=$(echo "$NEEDS_JSON" | jq -r '
to_entries
| map(select(.value.result == "failure" or .value.result == "cancelled"))
| map(.key)
| join(",")')
if [ -n "$failed" ]; then
echo "::error::Required jobs failed or were cancelled: $failed"
exit 1
fi
echo "All required jobs succeeded or were skipped via path filtering."