forked from isaac-sim/IsaacLab
-
Notifications
You must be signed in to change notification settings - Fork 3
219 lines (201 loc) · 8.45 KB
/
Copy patharm-ci.yml
File metadata and controls
219 lines (201 loc) · 8.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# 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
# aarch64 build + marker-gated tests on NVIDIA DGX Spark self-hosted runners.
#
# Split out of build.yaml (Docker + Tests) so this slow arm64 build+render owns
# its own workflow run. In build.yaml it shared the run with every test-* job,
# so the whole run stayed open until arm-ci finished (up to its 60-minute
# timeout) — and GitHub only exposes "Re-run failed jobs" once the entire run
# completes, forcing a fast test job that failed early to wait on arm-ci before
# it could be retried. As its own workflow, arm-ci no longer gates the main
# workflow's lifecycle, and it can be re-run independently.
#
# arm-ci is currently informational (continue-on-error), but it is wired to be
# promotable to a REQUIRED status check: it triggers on every PR and gates the
# expensive arm64 build behind the shared `changes` detector + `if:`. An
# irrelevant PR SKIPS the job (which branch protection reads as green) instead
# of never creating the check — a workflow-level `paths:` filter is deliberately
# avoided because a not-triggered required check stays pending forever and
# blocks the PR. This mirrors the `changes`+`if:` pattern build.yaml already
# uses for its required test jobs.
#
# Trigger parity with the former build.yaml job:
# - push to protected branches always runs (post-merge integration);
# - pull_request runs only when arm-relevant paths change (via `changes`+`if:`).
# endregion
name: ARM CI
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: read
env:
NGC_API_KEY: ${{ secrets.NGC_API_KEY }}
jobs:
# Shared change-detection gate. The trigger is unfiltered (see header) so the
# arm-ci check is always creatable; this decides whether the expensive jobs
# actually run. Lists arm-ci's real inputs — including the root files
# Dockerfile.base copies (pyproject.toml, environment.yml, isaaclab.*) that a
# path filter would otherwise miss.
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: arm-ci
triggered-jobs-pr: arm-ci
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 (OV pins + Docker copy)
^environment\.yml$ :: Conda env (Docker copy)
^isaaclab\. :: isaaclab.sh/.bat entrypoints (Docker copy)
^\.github/workflows/arm-ci\.yml$ :: This workflow file
^\.github/workflows/config\.yaml$ :: Base image config
^\.github/actions/ :: CI actions
# Loads the Isaac Sim base image name/tag from config.yaml and computes the
# per-run CI image tag. Inlined here (rather than shared with build.yaml)
# because arm-ci builds its own independent -arm64 image and only needs three
# of the values build.yaml's config job produces.
config:
name: Load Config
needs: [changes]
if: needs.changes.outputs.should_run == 'true'
runs-on: ubuntu-latest
outputs:
isaacsim_image_name: ${{ steps.load.outputs.isaacsim_image_name }}
isaacsim_image_tag: ${{ steps.load.outputs.isaacsim_image_tag }}
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"
# NOTE: this ci_image_tag formula is intentionally duplicated in build.yaml's
# config job — the two images are independent (-arm64 here vs x86 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}"
# aarch64 build + marker-gated tests on NVIDIA DGX Spark self-hosted runners.
# Build and test must share one runner because ECR is not wired for arm64 —
# the locally-built image cannot be handed off across machines.
arm-ci:
name: Build & Test
runs-on: [self-hosted, arm64]
needs: [changes, config]
if: needs.changes.outputs.should_run == 'true'
timeout-minutes: 60
continue-on-error: true
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
lfs: true
- name: Build base image (linux/arm64)
uses: ./.github/actions/docker-build
with:
image-tag: ${{ needs.config.outputs.ci_image_tag }}-arm64
isaacsim-base-image: ${{ needs.config.outputs.isaacsim_image_name }}
isaacsim-version: ${{ needs.config.outputs.isaacsim_image_tag }}
dockerfile-path: docker/Dockerfile.base
platform: linux/arm64
# The Spark runner is long-lived self-hosted with no ECR, so its local
# deps-cache tags accumulate; evict ones older than 14 days each run.
evict-stale-cache: "true"
- name: Resolve OV runtime pins from pyproject
uses: ./.github/actions/resolve-ov-pins
id: ov_pins
- name: Run arm_ci marker tests
uses: ./.github/actions/run-tests
with:
test-path: tools
result-file: arm-ci-report.xml
container-name: isaac-lab-arm-ci-${{ github.run_id }}-${{ github.run_attempt }}
image-tag: ${{ needs.config.outputs.ci_image_tag }}-arm64
extra-pip-packages: "${{ steps.ov_pins.outputs.ovrtx }} ${{ steps.ov_pins.outputs.ovphysx }}"
test-k-expr: not ovphysx
ci-marker: arm_ci
volume-mount-source: ${{ github.workspace }}
- name: Run arm_ci OVPhysX marker tests
uses: ./.github/actions/run-tests
with:
test-path: tools
result-file: arm-ci-ovphysx-report.xml
container-name: isaac-lab-arm-ci-ovphysx-${{ github.run_id }}-${{ github.run_attempt }}
image-tag: ${{ needs.config.outputs.ci_image_tag }}-arm64
extra-pip-packages: "${{ steps.ov_pins.outputs.ovrtx }} ${{ steps.ov_pins.outputs.ovphysx }}"
test-k-expr: ovphysx
ci-marker: arm_ci
volume-mount-source: ${{ github.workspace }}
- name: Run shared Cartpole smoke
uses: ./.github/actions/run-tests
with:
test-path: source/isaaclab/test/install_ci/misc/cartpole_training_smoke.py
result-file: arm-ci-cartpole-smoke-report.xml
container-name: isaac-lab-arm-ci-cartpole-${{ github.run_id }}-${{ github.run_attempt }}
image-tag: ${{ needs.config.outputs.ci_image_tag }}-arm64
volume-mount-source: ${{ github.workspace }}
- name: Upload test reports
if: always()
uses: actions/upload-artifact@v7
with:
name: arm-ci-reports
path: reports/
retention-days: 7