From f2e3b91b6f09b07d3dff2a244cb2c4d0fdf80b5a Mon Sep 17 00:00:00 2001 From: Jiwen Cai Date: Sun, 25 Oct 2026 19:31:24 -0700 Subject: [PATCH 1/5] ci: make GPU tests and wheel publishing configurable Signed-off-by: Jiwen Cai --- .github/workflows/build-ubuntu.yml | 78 +++++++++++++++++++----------- CONTRIBUTING.md | 22 +++++++++ 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index 45e61cd104..d7ae68dacd 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -26,7 +26,11 @@ env: # commit only needs to be recent enough to contain that baseline. Update the # commit and its release-date comment together. VCPKG_COMMIT: d015e31e90838a4c9dfa3eed45979bc70d9357fc # 2026.05.25 - NO_GPU_ARM: "1" + # Repository variables use 1 to disable, 0 to enable; see CONTRIBUTING.md. + # Infrastructure defaults follow the canonical repository ID across renames. + NO_GPU_TESTS: ${{ vars.NO_GPU_TESTS || (github.repository_id == '1092046207' && '0' || '1') }} + NO_GPU_ARM: ${{ vars.NO_GPU_ARM || '1' }} + NO_WHEEL_PUBLISH: ${{ vars.NO_WHEEL_PUBLISH || (github.repository_id == '1092046207' && '0' || '1') }} jobs: build-ubuntu: @@ -534,19 +538,29 @@ jobs: uv run --python 3.11 --directory tests/python/packaging --extra dev \ pytest -v test_wheel_contents.py - # Jobs `if:` conditions cannot see the `matrix` context, so arm64 GPU test - # runs are skipped by computing the test matrix here instead: when - # NO_GPU_ARM=1, arm64 drops out of the matrix entirely (no self-hosted arm64 - # GPU runner is claimed) while build-ubuntu still builds arm64 unconditionally. - resolve-test-arches: + # Job conditions cannot read workflow env; resolve it into job outputs. + # Keep a nonempty matrix even when GPU jobs are disabled by their conditions. + resolve-ci-config: runs-on: ubuntu-22.04 permissions: {} outputs: arches: ${{ steps.resolve.outputs.arches }} + gpu-tests: ${{ steps.resolve.outputs.gpu-tests }} + wheel-publish: ${{ steps.resolve.outputs.wheel-publish }} steps: - - name: Resolve GPU test architectures + - name: Resolve CI capabilities and GPU test architectures id: resolve run: | + set -euo pipefail + for flag in NO_GPU_TESTS NO_GPU_ARM NO_WHEEL_PUBLISH; do + case "${!flag}" in + 0|1) ;; + *) echo "::error::${flag} must be 0 or 1"; exit 1 ;; + esac + done + # Boolean outputs fail closed: a missing expression value can equal '0'. + echo "gpu-tests=$([[ "$NO_GPU_TESTS" == "0" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "wheel-publish=$([[ "$NO_WHEEL_PUBLISH" == "0" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" if [[ "$NO_GPU_ARM" == "1" ]]; then echo 'arches=["x64"]' >> "$GITHUB_OUTPUT" else @@ -561,12 +575,13 @@ jobs: runs-on: [self-hosted, linux, gpu, "${{ matrix.arch }}"] permissions: contents: read - needs: [build-ubuntu, resolve-test-arches] + needs: [build-ubuntu, resolve-ci-config] + if: ${{ needs.resolve-ci-config.outputs.gpu-tests == 'true' }} strategy: fail-fast: ${{ github.event_name == 'pull_request' }} matrix: - arch: ${{ fromJson(needs.resolve-test-arches.outputs.arches) }} + arch: ${{ fromJson(needs.resolve-ci-config.outputs.arches) }} steps: - name: Download viz test binaries @@ -753,13 +768,14 @@ jobs: runs-on: [self-hosted, linux, gpu, "${{ matrix.arch }}"] permissions: contents: read - needs: [build-ubuntu, resolve-test-arches] + needs: [build-ubuntu, resolve-ci-config] + if: ${{ needs.resolve-ci-config.outputs.gpu-tests == 'true' }} strategy: fail-fast: ${{ github.event_name == 'pull_request' }} matrix: python_version: ['3.11', '3.12', '3.13'] - arch: ${{ fromJson(needs.resolve-test-arches.outputs.arches) }} + arch: ${{ fromJson(needs.resolve-ci-config.outputs.arches) }} steps: - name: Checkout code @@ -798,13 +814,14 @@ jobs: runs-on: [self-hosted, linux, gpu, "${{ matrix.arch }}"] permissions: contents: read - needs: [build-ubuntu, resolve-test-arches] + needs: [build-ubuntu, resolve-ci-config] + if: ${{ needs.resolve-ci-config.outputs.gpu-tests == 'true' }} strategy: fail-fast: ${{ github.event_name == 'pull_request' }} matrix: python_version: ['3.12'] - arch: ${{ fromJson(needs.resolve-test-arches.outputs.arches) }} + arch: ${{ fromJson(needs.resolve-ci-config.outputs.arches) }} steps: - name: Checkout code @@ -1120,13 +1137,13 @@ jobs: cat "$LOG_FILE" 2>/dev/null || echo "No log captured" echo "Live CloudXR and Wuji plugin bring-up verified for mode $MODE (${{ env.ROS_DISTRO }}, ${{ matrix.arch }})." - # These are the actual dependency jobs for publish-wheel. publish-wheel - # depends only on wheel-gate so the dependency list lives in one place, while - # this gate still runs for fork PRs where publish-wheel is intentionally skipped. + # Validation dependencies live here, including for runs that do not publish. + # Only explicitly disabled GPU jobs may be skipped; failures still fail the gate. wheel-gate: runs-on: ubuntu-22.04 permissions: {} needs: + - resolve-ci-config - build-ubuntu - test-sbom-collector - test-viz-gpu @@ -1139,13 +1156,18 @@ jobs: - name: Require wheel dependencies success env: NEEDS_JSON: ${{ toJson(needs) }} + GPU_TESTS: ${{ needs.resolve-ci-config.outputs.gpu-tests }} run: | set -euo pipefail failed_jobs="$( - jq -r ' + jq -r --arg gpu_tests "$GPU_TESTS" ' to_entries[] | select(.value.result != "success") + | select(( + $gpu_tests == "false" and .value.result == "skipped" + and (.key == "test-viz-gpu" or .key == "test-cloudxr" or .key == "test-teleop-ros2") + ) | not) | "\(.key) completed with result: \(.value.result)" ' <<< "${NEEDS_JSON}" )" @@ -1155,13 +1177,14 @@ jobs: exit 1 fi - echo "All wheel dependency jobs completed successfully" + echo "All required wheel dependency jobs completed successfully" publish-sbom-evidence: # durable copies attached to the GitHub release # Attach durable evidence to releases; Actions artifacts expire. runs-on: ubuntu-22.04 needs: - wheel-gate + - resolve-ci-config permissions: contents: write timeout-minutes: 20 @@ -1172,6 +1195,8 @@ jobs: if: >- !cancelled() && needs.wheel-gate.result == 'success' + && needs.resolve-ci-config.outputs.gpu-tests == 'true' + && needs.resolve-ci-config.outputs.wheel-publish == 'true' && github.repository_id == '1092046207' && startsWith(github.ref, 'refs/tags/v') @@ -1259,25 +1284,20 @@ jobs: permissions: {} needs: - wheel-gate + - resolve-ci-config outputs: wheel_paths: ${{ steps.upload-artifactory.outputs.wheel_paths }} environment: dev timeout-minutes: 10 - # Publish only for same-repo runs (pushes or non-fork PRs). github.repository - # is the base repo even for fork PRs, so compare the PR head repo instead. - # `!cancelled()` because a skip propagates through the whole dependency - # chain, not one level: a test job that does not run -- an empty arch matrix, - # say -- skips `wheel-gate`'s dependents even though `wheel-gate` itself - # succeeded through `always()`. The result check below is what should gate - # this job, and without a status function it never gets the chance. - # - # Continuations sit at the block's indentation: a folded scalar keeps the - # newline of a more-indented line, so the expression would reach the - # evaluator with a newline inside it. + # A CPU-only gate pass must not publish wheels. Keep the same-repo PR check: + # github.repository identifies the base repository even for fork PRs. + # !cancelled() avoids inherited skip propagation; wheel-gate owns validation. if: >- !cancelled() && needs.wheel-gate.result == 'success' + && needs.resolve-ci-config.outputs.gpu-tests == 'true' + && needs.resolve-ci-config.outputs.wheel-publish == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae507e62ef..662f6f1ac6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,8 +60,30 @@ file location, preserving existing attribution and explicit third-party exceptio Review and stage any automatic edits, then commit again. ## CI + GitHub Actions builds the default targets and runs tests. +The Build Ubuntu workflow reads repository variables from **Settings → Secrets and +variables → Actions → Variables**. Set a flag to `1` to disable that capability or +`0` to enable it; unset variables use these defaults: + +| Variable | Canonical repository | Other repositories | Controls | +|----------|----------------------|--------------------|----------| +| `NO_GPU_TESTS` | `0` | `1` | Self-hosted visualization, CloudXR, and ROS2 GPU tests | +| `NO_GPU_ARM` | `1` | `1` | ARM64 GPU tests; CPU builds still cover ARM64 | +| `NO_WHEEL_PUBLISH` | `0` | `1` | Artifactory wheels, release SBOM evidence, and the downstream Kitmaker chain | + +Defaults follow the repository running the workflow, so pull requests targeting +the canonical repository retain GPU validation even when their source is a fork. + +CPU builds, unit tests, sanitizers, and SBOM checks remain enabled. The wheel gate +accepts GPU jobs skipped by `NO_GPU_TESTS=1`, but still rejects failures, +cancellations, and unexpected skips. Publishing also requires GPU tests to be +enabled and successful; a CPU-only run cannot publish wheels. Existing event, +repository, and environment restrictions still apply. Only enable a capability +after its runners and credentials are configured. Docs deployment has separate +canonical-repository guards. + ## Pull Requests 1. Create a feature branch 2. Ensure builds pass locally and in CI From e91293f308aefb17608c265ac9df71487a0ddb36 Mon Sep 17 00:00:00 2001 From: Jiwen Cai Date: Sun, 25 Oct 2026 19:38:25 -0700 Subject: [PATCH 2/5] ci: keep capability guidance in the workflow Signed-off-by: Jiwen Cai --- .github/workflows/build-ubuntu.yml | 3 ++- CONTRIBUTING.md | 22 ---------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index d7ae68dacd..a988f76fae 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -26,7 +26,8 @@ env: # commit only needs to be recent enough to contain that baseline. Update the # commit and its release-date comment together. VCPKG_COMMIT: d015e31e90838a4c9dfa3eed45979bc70d9357fc # 2026.05.25 - # Repository variables use 1 to disable, 0 to enable; see CONTRIBUTING.md. + # Repository Actions variables use 1 to disable, 0 to enable. + # Keep workflow-specific configuration guidance here beside the defaults. # Infrastructure defaults follow the canonical repository ID across renames. NO_GPU_TESTS: ${{ vars.NO_GPU_TESTS || (github.repository_id == '1092046207' && '0' || '1') }} NO_GPU_ARM: ${{ vars.NO_GPU_ARM || '1' }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 662f6f1ac6..ae507e62ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,30 +60,8 @@ file location, preserving existing attribution and explicit third-party exceptio Review and stage any automatic edits, then commit again. ## CI - GitHub Actions builds the default targets and runs tests. -The Build Ubuntu workflow reads repository variables from **Settings → Secrets and -variables → Actions → Variables**. Set a flag to `1` to disable that capability or -`0` to enable it; unset variables use these defaults: - -| Variable | Canonical repository | Other repositories | Controls | -|----------|----------------------|--------------------|----------| -| `NO_GPU_TESTS` | `0` | `1` | Self-hosted visualization, CloudXR, and ROS2 GPU tests | -| `NO_GPU_ARM` | `1` | `1` | ARM64 GPU tests; CPU builds still cover ARM64 | -| `NO_WHEEL_PUBLISH` | `0` | `1` | Artifactory wheels, release SBOM evidence, and the downstream Kitmaker chain | - -Defaults follow the repository running the workflow, so pull requests targeting -the canonical repository retain GPU validation even when their source is a fork. - -CPU builds, unit tests, sanitizers, and SBOM checks remain enabled. The wheel gate -accepts GPU jobs skipped by `NO_GPU_TESTS=1`, but still rejects failures, -cancellations, and unexpected skips. Publishing also requires GPU tests to be -enabled and successful; a CPU-only run cannot publish wheels. Existing event, -repository, and environment restrictions still apply. Only enable a capability -after its runners and credentials are configured. Docs deployment has separate -canonical-repository guards. - ## Pull Requests 1. Create a feature branch 2. Ensure builds pass locally and in CI From 748dc7f9bb182303b0277e7e8eb9358a8b54cefe Mon Sep 17 00:00:00 2001 From: Jiwen Cai Date: Sun, 25 Oct 2026 19:59:29 -0700 Subject: [PATCH 3/5] ci: define capability controls directly in workflow env Signed-off-by: Jiwen Cai --- .github/workflows/build-ubuntu.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index a988f76fae..1175119289 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -26,12 +26,11 @@ env: # commit only needs to be recent enough to contain that baseline. Update the # commit and its release-date comment together. VCPKG_COMMIT: d015e31e90838a4c9dfa3eed45979bc70d9357fc # 2026.05.25 - # Repository Actions variables use 1 to disable, 0 to enable. - # Keep workflow-specific configuration guidance here beside the defaults. + # Keep capability settings and guidance in workflow env (1 disables, 0 enables). # Infrastructure defaults follow the canonical repository ID across renames. - NO_GPU_TESTS: ${{ vars.NO_GPU_TESTS || (github.repository_id == '1092046207' && '0' || '1') }} - NO_GPU_ARM: ${{ vars.NO_GPU_ARM || '1' }} - NO_WHEEL_PUBLISH: ${{ vars.NO_WHEEL_PUBLISH || (github.repository_id == '1092046207' && '0' || '1') }} + NO_GPU_TESTS: ${{ github.repository_id == '1092046207' && '0' || '1' }} + NO_GPU_ARM: "1" + NO_WHEEL_PUBLISH: ${{ github.repository_id == '1092046207' && '0' || '1' }} jobs: build-ubuntu: From f94434ad5716e7e64cb4eed002248e9d0e76f312 Mon Sep 17 00:00:00 2001 From: Jiwen Cai Date: Sun, 25 Oct 2026 20:21:06 -0700 Subject: [PATCH 4/5] ci: keep publication independent of GPU test enablement Signed-off-by: Jiwen Cai --- .github/workflows/build-ubuntu.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index 1175119289..ef44dcbb5c 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -1139,6 +1139,7 @@ jobs: # Validation dependencies live here, including for runs that do not publish. # Only explicitly disabled GPU jobs may be skipped; failures still fail the gate. + # Publishing relies on this gate independently of which tests are enabled. wheel-gate: runs-on: ubuntu-22.04 permissions: {} @@ -1195,7 +1196,6 @@ jobs: if: >- !cancelled() && needs.wheel-gate.result == 'success' - && needs.resolve-ci-config.outputs.gpu-tests == 'true' && needs.resolve-ci-config.outputs.wheel-publish == 'true' && github.repository_id == '1092046207' && startsWith(github.ref, 'refs/tags/v') @@ -1290,13 +1290,11 @@ jobs: environment: dev timeout-minutes: 10 - # A CPU-only gate pass must not publish wheels. Keep the same-repo PR check: - # github.repository identifies the base repository even for fork PRs. - # !cancelled() avoids inherited skip propagation; wheel-gate owns validation. + # github.repository identifies the base even for fork PRs; check the head too. + # !cancelled() avoids inherited skip propagation. if: >- !cancelled() && needs.wheel-gate.result == 'success' - && needs.resolve-ci-config.outputs.gpu-tests == 'true' && needs.resolve-ci-config.outputs.wheel-publish == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) From a90f3ffd74d7f5f138a18f37a5cabd96ac1d06e2 Mon Sep 17 00:00:00 2001 From: Jiwen Cai Date: Sun, 25 Oct 2026 22:21:28 -0700 Subject: [PATCH 5/5] ci: preserve CPU coverage and downstream publication after GPU skips Signed-off-by: Jiwen Cai --- .github/workflows/build-ubuntu.yml | 62 ++++++++++++++++++------------ src/viz/AGENTS.md | 4 +- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index ef44dcbb5c..38b39ee786 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -28,6 +28,7 @@ env: VCPKG_COMMIT: d015e31e90838a4c9dfa3eed45979bc70d9357fc # 2026.05.25 # Keep capability settings and guidance in workflow env (1 disables, 0 enables). # Infrastructure defaults follow the canonical repository ID across renames. + # Test and publication controls remain independent, including on release tags. NO_GPU_TESTS: ${{ github.repository_id == '1092046207' && '0' || '1' }} NO_GPU_ARM: "1" NO_WHEEL_PUBLISH: ${{ github.repository_id == '1092046207' && '0' || '1' }} @@ -538,8 +539,8 @@ jobs: uv run --python 3.11 --directory tests/python/packaging --extra dev \ pytest -v test_wheel_contents.py - # Job conditions cannot read workflow env; resolve it into job outputs. - # Keep a nonempty matrix even when GPU jobs are disabled by their conditions. + # Job conditions cannot read workflow env or matrix; expose configuration as + # outputs and remove unsupported architectures before matrix expansion. resolve-ci-config: runs-on: ubuntu-22.04 permissions: {} @@ -553,7 +554,7 @@ jobs: run: | set -euo pipefail for flag in NO_GPU_TESTS NO_GPU_ARM NO_WHEEL_PUBLISH; do - case "${!flag}" in + case "${!flag-}" in 0|1) ;; *) echo "::error::${flag} must be 0 or 1"; exit 1 ;; esac @@ -811,11 +812,14 @@ jobs: ./scripts/run_tests_with_cloudxr.sh --python-version ${{ matrix.python_version }} test-teleop-ros2: - runs-on: [self-hosted, linux, gpu, "${{ matrix.arch }}"] + # Unit tests and MCAP replay require no GPU; only live CloudXR does. + runs-on: >- + ${{ needs.resolve-ci-config.outputs.gpu-tests == 'true' + && fromJSON(format('["self-hosted", "linux", "gpu", "{0}"]', matrix.arch)) + || (matrix.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04') }} permissions: contents: read needs: [build-ubuntu, resolve-ci-config] - if: ${{ needs.resolve-ci-config.outputs.gpu-tests == 'true' }} strategy: fail-fast: ${{ github.event_name == 'pull_request' }} @@ -832,16 +836,6 @@ jobs: - name: Install uv uses: ./.github/actions/setup-uv - - name: Download install artifacts - uses: actions/download-artifact@v7 - with: - name: isaacteleop-install-release-${{ matrix.arch }}-py${{ matrix.python_version }} - - - name: Extract tarball to preserve permissions - run: | - mkdir -p install - tar -xvf isaacteleop-install.tar -C install - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 @@ -886,11 +880,8 @@ jobs: "source /usr/local/bin/teleop-env-setup && \ exec uv run --with pytest --no-sync pytest -v --tb=short tests" - # MCAP replay path: feed a recorded fixture through the node - # (SessionMode.REPLAY, no CloudXR runtime / GPU) across all teleop modes and - # verify the published topics. The cheaper, deterministic check; runs before - # the live bring-up below, which reuses the same image and removes it on - # teardown. + # Replay a recorded fixture across teleop modes and verify published topics + # without a CloudXR runtime or GPU. Live bring-up reuses this image when enabled. - name: Verify application modes (MCAP replay) run: | set -euo pipefail @@ -1007,6 +998,7 @@ jobs: # real in-process CloudXR runtime and requires the bundled Wuji plugin to # start through TeleopSession. No XR client or glove is required. - name: Verify live CloudXR bring-up + if: ${{ needs.resolve-ci-config.outputs.gpu-tests == 'true' }} run: | set -euo pipefail @@ -1037,7 +1029,6 @@ jobs: cleanup() { docker logs "$RUN_NAME" > "$LOG_FILE" 2>&1 || true docker rm -f "$RUN_NAME" >/dev/null 2>&1 || true - docker image rm -f "$IMAGE" >/dev/null 2>&1 || true } trap cleanup EXIT @@ -1137,6 +1128,10 @@ jobs: cat "$LOG_FILE" 2>/dev/null || echo "No log captured" echo "Live CloudXR and Wuji plugin bring-up verified for mode $MODE (${{ env.ROS_DISTRO }}, ${{ matrix.arch }})." + - name: Remove teleop_ros2 image + if: ${{ always() }} + run: docker image rm -f teleop_ros2_ref:${{ env.ROS_DISTRO }} >/dev/null 2>&1 || true + # Validation dependencies live here, including for runs that do not publish. # Only explicitly disabled GPU jobs may be skipped; failures still fail the gate. # Publishing relies on this gate independently of which tests are enabled. @@ -1158,16 +1153,19 @@ jobs: env: NEEDS_JSON: ${{ toJson(needs) }} GPU_TESTS: ${{ needs.resolve-ci-config.outputs.gpu-tests }} + WHEEL_PUBLISH: ${{ needs.resolve-ci-config.outputs.wheel-publish }} run: | set -euo pipefail + # Keep the skipped-job allowlist aligned with the job-level GPU conditions. + # test-teleop-ros2 remains required because its CPU checks always run. failed_jobs="$( jq -r --arg gpu_tests "$GPU_TESTS" ' to_entries[] | select(.value.result != "success") | select(( $gpu_tests == "false" and .value.result == "skipped" - and (.key == "test-viz-gpu" or .key == "test-cloudxr" or .key == "test-teleop-ros2") + and (.key == "test-viz-gpu" or .key == "test-cloudxr") ) | not) | "\(.key) completed with result: \(.value.result)" ' <<< "${NEEDS_JSON}" @@ -1178,6 +1176,17 @@ jobs: exit 1 fi + if [[ "$GPU_TESTS" == "false" ]]; then + skipped_jobs="$(jq -r '[to_entries[] | select(.value.result == "skipped") | .key] | join(", ")' <<< "$NEEDS_JSON")" + message="NO_GPU_TESTS=1: skipped jobs: ${skipped_jobs:-none}; test-teleop-ros2 runs CPU checks only, without live CloudXR." + echo "::notice::$message" + echo "$message" >> "$GITHUB_STEP_SUMMARY" + if [[ "$WHEEL_PUBLISH" == "true" ]]; then + echo "::warning::Wheel publishing is enabled without GPU validation." + echo "Wheel publishing is enabled without GPU validation." >> "$GITHUB_STEP_SUMMARY" + fi + fi + echo "All required wheel dependency jobs completed successfully" publish-sbom-evidence: # durable copies attached to the GitHub release @@ -1290,8 +1299,11 @@ jobs: environment: dev timeout-minutes: 10 + # Skips propagate through the full dependency chain, even past a successful + # wheel-gate. publish-wheel, kitmaker, and kitmaker-status need !cancelled() + # plus their immediate dependency's result to continue after intentional skips. + # Keep folded-scalar continuations equally indented so YAML folds to one line. # github.repository identifies the base even for fork PRs; check the head too. - # !cancelled() avoids inherited skip propagation. if: >- !cancelled() && needs.wheel-gate.result == 'success' @@ -1494,7 +1506,7 @@ jobs: environment: release permissions: contents: read - if: ${{ github.event_name == 'push' && needs.publish-wheel.result == 'success' }} + if: ${{ !cancelled() && github.event_name == 'push' && needs.publish-wheel.result == 'success' }} steps: - name: Submit wheel release to Kitmaker @@ -1604,7 +1616,7 @@ jobs: - kitmaker permissions: contents: read - if: ${{ needs.kitmaker.result == 'success' }} + if: ${{ !cancelled() && needs.kitmaker.result == 'success' }} steps: - name: Monitor Kitmaker release status diff --git a/src/viz/AGENTS.md b/src/viz/AGENTS.md index 20216b8ee7..fe94a95dba 100644 --- a/src/viz/AGENTS.md +++ b/src/viz/AGENTS.md @@ -194,8 +194,8 @@ that library to compose fixtures. Today: - **`test-viz-gpu`** (self-hosted GPU runner, x64 + arm64): downloads the `viz-tests-${arch}` artifact and runs each binary with the `[gpu]` filter. This is where the GPU paths actually execute. -- **`publish-wheel`** depends on `test-viz-gpu` succeeding — wheels are - not published if any `[gpu]` test fails. +- **`publish-wheel`** requires `wheel-gate` to pass. Enabled GPU tests must + succeed; `NO_GPU_TESTS=1` explicitly exempts the GPU jobs. When you add a new `viz__tests` executable, no CI changes needed: the package step globs `viz_*_tests` and the runner loops over them.