Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 109 additions & 30 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -341,16 +341,67 @@ jobs:

#endregion

#region compute affected packages
compute-affected-packages:
name: Compute Affected CI Jobs
runs-on: ubuntu-latest
needs: [changes]
if: needs.changes.outputs.run_docker_tests == 'true'
outputs:
affected_jobs: ${{ steps.compute.outputs.affected_jobs }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pyyaml
run: pip install pyyaml --quiet
- name: Compute affected jobs from file-level import graph
id: compute
env:
BASE_REF: ${{ github.event.pull_request.base.ref || github.event.before }}
EVENT_NAME: ${{ github.event_name }}
run: |
set -euo pipefail

if [ "$EVENT_NAME" = "pull_request" ]; then
# Find the merge base so rebased PRs compare correctly
git fetch origin "$BASE_REF" --depth=100 2>/dev/null || true
MERGE_BASE=$(git merge-base HEAD "origin/${BASE_REF}" 2>/dev/null || echo "")
REF="${MERGE_BASE:-origin/${BASE_REF}}"

AFFECTED=$(python3 tools/package_impact_graph.py --since "$REF" --json 2>/dev/null \
| python3 -c "import json,sys; m=json.load(sys.stdin); print(json.dumps(sorted(m['jobs'].keys())))")
else
# Non-PR push: run all jobs (fail-open). Derive the full list from
# the graph so it stays in sync when new jobs are added to build.yaml.
AFFECTED=$(python3 tools/package_impact_graph.py 2>/dev/null \
| python3 -c "import json,sys; g=json.load(sys.stdin); print(json.dumps(g['all_ci_jobs']))")
fi

echo "affected_jobs=${AFFECTED}" >> "$GITHUB_OUTPUT"
echo "### Affected CI jobs" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo '```json' >> "$GITHUB_STEP_SUMMARY"
echo "${AFFECTED}" | python3 -m json.tool >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
#endregion

#region test jobs
test-isaaclab-tasks:
name: isaaclab_tasks [1/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
continue-on-error: true
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-tasks'))
Comment on lines 400 to +404

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Fail-open broken when compute-affected-packages fails

In GitHub Actions, when a job listed in needs fails (not skipped — actually errors), GitHub automatically cancels dependent jobs before evaluating their if condition. The condition needs.compute-affected-packages.result != 'success' is never reached because the test job is pre-emptively skipped. The PR description promises fail-open behavior ("any failure in the compute job fails open"), but the current implementation delivers fail-closed: if the script crashes or git errors out, every test job is silently cancelled.

To honour the fail-open contract each test job's if needs to begin with always() && so GitHub evaluates the expression instead of auto-cancelling. The same fix applies to all other test jobs that share the same if pattern.

steps:
- uses: actions/checkout@v6
with:
Expand All @@ -372,10 +423,12 @@ jobs:
runs-on: [self-hosted, gpu]
timeout-minutes: 180
continue-on-error: true
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-tasks'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -397,10 +450,12 @@ jobs:
runs-on: [self-hosted, gpu]
timeout-minutes: 180
continue-on-error: true
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-tasks'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -421,10 +476,12 @@ jobs:
name: isaaclab (core) [1/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-core'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -444,10 +501,12 @@ jobs:
name: isaaclab (core) [2/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-core'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -467,10 +526,12 @@ jobs:
name: isaaclab (core) [3/3]
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-core'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -490,10 +551,12 @@ jobs:
name: isaaclab_rl
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-rl'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -512,10 +575,12 @@ jobs:
name: isaaclab_mimic
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-mimic'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -533,10 +598,12 @@ jobs:
name: isaaclab_contrib
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-contrib'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -554,10 +621,12 @@ jobs:
name: isaaclab_teleop
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-teleop'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -575,10 +644,12 @@ jobs:
name: isaaclab_visualizers
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-visualizers'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -596,10 +667,12 @@ jobs:
name: isaaclab_assets
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-assets'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -617,10 +690,12 @@ jobs:
name: isaaclab_newton
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-newton'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -638,10 +713,12 @@ jobs:
name: isaaclab_physx
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-physx'))
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -659,10 +736,12 @@ jobs:
name: isaaclab_ov
runs-on: [self-hosted, gpu]
timeout-minutes: 180
needs: [build, config]
needs: [build, config, compute-affected-packages]
if: >-
github.event_name != 'push' &&
needs.build.result == 'success'
needs.build.result == 'success' &&
(needs.compute-affected-packages.result != 'success' ||
contains(fromJSON(needs.compute-affected-packages.outputs.affected_jobs), 'test-isaaclab-ov'))
env:
USE_OVPHYSX_WHEELHOUSE: ${{ needs.config.outputs.ovphysx_wheelhouse_resource != '' && ((github.event_name == 'pull_request' && github.base_ref == 'develop' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name != 'pull_request' && github.ref_name == 'develop')) }}
steps:
Expand Down
Loading
Loading