feat(training): add NVIDIA ARM64 support for LeRobot 0.6.1 #3827
Workflow file for this run
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
| 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." |