Skip to content

Commit df15280

Browse files
committed
1 parent 47bfc79 commit df15280

21 files changed

Lines changed: 2364 additions & 595 deletions

.github/workflows/perf-regression-gate.yaml

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
# Performance Regression Gate
77
#
8+
# GPU jobs default to the RTX PRO 6000 runner label used by the upstream
9+
# deployment. Override with repo variable PERF_GATE_RUNS_ON, e.g. a JSON array
10+
# of runner labels.
11+
#
812
# Runs a matrix of benchmark tasks on self-hosted runners, compares
913
# results to the rolling baseline in angehu/perf-baselines, and posts a verdict
1014
# table to the job summary. Non-blocking by default (gate_config.json).
@@ -16,19 +20,27 @@
1620
# aggregate → download all bench artifacts, run oracle, update baselines
1721
# (self-hosted, gpu)
1822
#
19-
# Baseline updates are pushed to angehu/perf-baselines only from main,
20-
# develop, release or angehu/perf-gate-poc branches.
23+
# Baseline updates are published from protected-branch push events
24+
# (main/develop/release) plus angehu/perf-gate-poc while this POC is active.
25+
# Mirrored PR pushes under pull-request/<number> can run the gate on upstream
26+
# RTX runners; they are read-only unless PERF_GATE_ALLOW_MIRROR_BASELINE_UPDATE
27+
# is explicitly enabled as a temporary deployment escape hatch.
2128
#
2229
# backend_key: "{physics_backend}_{render_backend}" when render_backend is
2330
# set, otherwise just physics_backend. Matches TaskConfig.backend_key.
2431
# TODO: replace angehu/perf-baselines w/ real branch name
32+
# TODO: remove angehu/perf-gate-poc after deployment
2533

2634
name: Performance Regression Gate
2735

2836
on:
2937
pull_request:
30-
types: [opened, synchronize, reopened]
38+
types: [opened, synchronize, reopened, ready_for_review]
39+
branches: [main, develop, 'release/**']
40+
merge_group:
3141
branches: [main, develop, 'release/**']
42+
push:
43+
branches: [main, develop, 'release/**', angehu/perf-gate-poc, 'pull-request/**']
3244
workflow_dispatch:
3345

3446
concurrency:
@@ -37,13 +49,14 @@ concurrency:
3749

3850
permissions:
3951
contents: write
52+
pull-requests: read
4053

4154
env:
4255
CI_IMAGE_TAG: >-
4356
isaac-lab-ci:${{
4457
github.event_name == 'pull_request'
4558
&& format('pr-{0}', github.event.pull_request.number)
46-
|| github.ref_name
59+
|| 'sha'
4760
}}-${{ github.sha }}
4861
4962
jobs:
@@ -52,6 +65,7 @@ jobs:
5265
# ---------------------------------------------------------------------------
5366
config:
5467
name: Load Config
68+
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.draft == false }}
5569
runs-on: ubuntu-latest
5670
outputs:
5771
isaacsim_image_name: ${{ steps.load.outputs.isaacsim_image_name }}
@@ -82,7 +96,8 @@ jobs:
8296
# ---------------------------------------------------------------------------
8397
bench:
8498
name: Bench / ${{ matrix.task_id }} / ${{ matrix.physics_backend }}${{ matrix.render_backend != '' && format('_{0}', matrix.render_backend) || '' }}
85-
runs-on: [self-hosted, gpu]
99+
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.draft == false }}
100+
runs-on: ${{ fromJSON(vars.PERF_GATE_RUNS_ON || '["linux-amd64-gpu-rtxpro6000-latest-1"]') }}
86101
needs: [config]
87102
continue-on-error: true
88103
timeout-minutes: ${{ matrix.job_timeout_minutes }}
@@ -134,6 +149,16 @@ jobs:
134149
LOG_FILE="${ARTIFACT_DIR}/benchmark.log"
135150
136151
mkdir -p "${ARTIFACT_DIR}"
152+
GPU_MODEL="$(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -1 | xargs)"
153+
if [[ -z "${GPU_MODEL}" ]]; then
154+
GPU_MODEL="unknown-gpu"
155+
fi
156+
python3 tools/perf_regression_gate/write_launch_config.py \
157+
--task_id "${TASK_ID}" \
158+
--physics_backend "${PHYSICS_BACKEND}" \
159+
--render_backend "${RENDER_BACKEND}" \
160+
--gpu_model "${GPU_MODEL}" \
161+
--artifact_dir "${ARTIFACT_DIR}"
137162
138163
# Remove any stale container from a previous run attempt
139164
docker rm -f "${CONTAINER_NAME}" 2>/dev/null || true
@@ -142,10 +167,7 @@ jobs:
142167
# benchmark_non_rl.py accepts Hydra-style preset tokens (no leading dashes).
143168
# Physics is selected via the sim_backend token; render via renderer= token.
144169
# TODO: Update these tokens once benchmark_non_rl.py CLI flags are finalised.
145-
PRESET_TOKENS=""
146-
if [ -n "${RENDER_BACKEND}" ]; then
147-
PRESET_TOKENS="renderer=${RENDER_BACKEND}"
148-
fi
170+
HYDRA_ARGS="${{ matrix.hydra_args }}"
149171
150172
# Start the benchmark container in detached mode
151173
docker run -d --name "${CONTAINER_NAME}" \
@@ -172,7 +194,8 @@ jobs:
172194
--num_frames ${{ matrix.num_frames }} \
173195
--benchmark_backend json \
174196
--output_path /tmp/bench_out \
175-
${PRESET_TOKENS}
197+
${{ matrix.seed != '' && format('--seed {0}', matrix.seed) || '' }} \
198+
${HYDRA_ARGS}
176199
"
177200
178201
START=$(date +%s)
@@ -234,10 +257,7 @@ jobs:
234257
235258
docker rm -f "${CONTAINER_NAME}" 2>/dev/null || true
236259
237-
PRESET_TOKENS=""
238-
if [ -n "${RENDER_BACKEND}" ]; then
239-
PRESET_TOKENS="renderer=${RENDER_BACKEND}"
240-
fi
260+
HYDRA_ARGS="${{ matrix.hydra_args }}"
241261
242262
docker run -d --name "${CONTAINER_NAME}" \
243263
--init --stop-timeout 10 \
@@ -263,7 +283,8 @@ jobs:
263283
--num_frames ${{ matrix.num_frames }} \
264284
--benchmark_backend json \
265285
--output_path /tmp/bench_out \
266-
${PRESET_TOKENS}
286+
${{ matrix.seed != '' && format('--seed {0}', matrix.seed) || '' }} \
287+
${HYDRA_ARGS}
267288
"
268289
269290
START=$(date +%s)
@@ -327,6 +348,8 @@ jobs:
327348
--wall_time_s "${FINAL_WALL}" \
328349
--timeout_s "${{ matrix.bench_timeout_s }}" \
329350
--log_file "${ARTIFACT_DIR}/benchmark.log" \
351+
--launch_config "${ARTIFACT_DIR}/launch_config.json" \
352+
--gate_config tools/perf_regression_gate/gate_config.json \
330353
${EXTRA_FLAGS}
331354
332355
- name: Upload bench artifacts
@@ -361,21 +384,22 @@ jobs:
361384
# ---------------------------------------------------------------------------
362385
aggregate:
363386
name: Aggregate + Verdict
364-
runs-on: [self-hosted, gpu]
387+
runs-on: ${{ fromJSON(vars.PERF_GATE_RUNS_ON || '["linux-amd64-gpu-rtxpro6000-latest-1"]') }}
365388
needs: [bench]
366-
# Always run even when some bench jobs fail or are skipped
367-
if: always()
389+
# Always run for real gate attempts, even when some bench jobs fail.
390+
if: ${{ always() && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
368391

369392
steps:
370393
- name: Checkout Code
371394
uses: actions/checkout@v6
372395
with:
373396
fetch-depth: 0
374397

375-
# Create a local branch so _baseline_worktree can commit to it
398+
# Prime the remote-tracking baseline ref. aggregate.py refetches immediately
399+
# before reading and again inside the transactional push retry loop.
376400
- name: Fetch baselines branch
377401
run: |
378-
git fetch origin angehu/perf-baselines:angehu/perf-baselines || \
402+
git fetch origin +refs/heads/angehu/perf-baselines:refs/remotes/origin/angehu/perf-baselines || \
379403
echo "::warning::Baseline branch not found; gate will run as a seed run (no baseline comparison)"
380404
381405
- name: Download bench artifacts
@@ -385,24 +409,31 @@ jobs:
385409
path: artifacts/
386410
merge-multiple: false
387411

412+
- name: Resolve gate context
413+
id: gate_context
414+
env:
415+
ALLOW_MIRROR_UPDATE: ${{ vars.PERF_GATE_ALLOW_MIRROR_BASELINE_UPDATE || 'false' }}
416+
GITHUB_TOKEN: ${{ github.token }}
417+
run: |
418+
python3 tools/perf_regression_gate/github_gate_context.py
419+
388420
- name: Run aggregate oracle
389421
id: aggregate
390422
run: |
391-
ALLOW_UPDATE="false"
392-
if [[ "${{ github.ref }}" == "refs/heads/develop" || \
393-
"${{ github.ref }}" == "refs/heads/angehu/perf-gate-poc" ]]; then
394-
ALLOW_UPDATE="true"
423+
GPU_MODEL="$(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -1 | xargs)"
424+
if [[ -z "${GPU_MODEL}" ]]; then
425+
GPU_MODEL="unknown-gpu"
395426
fi
396427
python3 tools/perf_regression_gate/aggregate.py \
397428
--artifacts_dir artifacts/ \
398-
--gpu_model L40S \
429+
--gpu_model "${GPU_MODEL}" \
399430
--gate_config tools/perf_regression_gate/gate_config.json \
400431
--baseline_branch angehu/perf-baselines \
401-
--allow_baseline_update "${ALLOW_UPDATE}" \
432+
--baseline_remote origin \
433+
--baseline_push_retries 3 \
434+
--base_sha "${{ steps.gate_context.outputs.base_sha }}" \
435+
--target_branch "${{ steps.gate_context.outputs.target_branch }}" \
436+
--source_branch "${{ steps.gate_context.outputs.source_branch }}" \
437+
--allow_baseline_update "${{ steps.gate_context.outputs.allow_update }}" \
438+
--trusted_source "${{ steps.gate_context.outputs.trusted_source }}" \
402439
--summary_file "${GITHUB_STEP_SUMMARY}"
403-
404-
# Push baseline updates only from eligible branches
405-
- name: Push baseline updates
406-
if: steps.aggregate.outputs.baselines_updated == 'true'
407-
run: |
408-
git push origin angehu/perf-baselines

0 commit comments

Comments
 (0)