Skip to content

Merge branch 'main' into fix-program-debug #5553

Merge branch 'main' into fix-program-debug

Merge branch 'main' into fix-program-debug #5553

Workflow file for this run

# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
# Note: This name is referred to in the test job, so make sure any changes are sync'd up!
# Further this is referencing a run in the backport branch to fetch old bindings.
name: "CI"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
on:
push:
branches:
- "pull-request/[0-9]+"
- "main"
tags:
# Build release artifacts from tag refs so setuptools-scm resolves exact
# release versions instead of .dev+local variants.
- "v*"
- "cuda-core-v*"
- "cuda-pathfinder-v*"
schedule:
# every 24 hours at midnight UTC
- cron: "0 0 * * *"
workflow_dispatch: {}
jobs:
ci-vars:
if: ${{ github.repository_owner == 'nvidia' }}
runs-on: ubuntu-latest
outputs:
CUDA_BUILD_VER: ${{ steps.get-vars.outputs.cuda_build_ver }}
CUDA_PREV_BUILD_VER: ${{ steps.get-vars.outputs.cuda_prev_build_ver }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
- name: Get CUDA build versions
id: get-vars
run: |
cuda_build_ver=$(yq '.cuda.build.version' ci/versions.yml)
echo "cuda_build_ver=$cuda_build_ver" >> $GITHUB_OUTPUT
cuda_prev_build_ver=$(yq '.cuda.prev_build.version' ci/versions.yml)
echo "cuda_prev_build_ver=$cuda_prev_build_ver" >> $GITHUB_OUTPUT
should-skip:
if: ${{ github.repository_owner == 'nvidia' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
skip: ${{ steps.get-should-skip.outputs.skip }}
doc-only: ${{ steps.get-should-skip.outputs.doc_only }}
base-ref: ${{ steps.get-should-skip.outputs.base_ref }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Compute whether to skip builds and tests
id: get-should-skip
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euxo pipefail
if ${{ startsWith(github.ref_name, 'pull-request/') }}; then
pr_number="$(grep -Po '(\d+)$' <<< '${{ github.ref_name }}')"
pr="$(gh pr view "${pr_number}" --json baseRefName,title)"
pr_title="$(jq -r '.title' <<< "${pr}")"
base_ref="$(jq -r '.baseRefName' <<< "${pr}")"
skip="$(echo "${pr_title}" | grep -q '\[no-ci\]' && echo true || echo false)"
doc_only="$(echo "${pr_title}" | grep -q '\[doc-only\]' && echo true || echo false)"
else
skip=false
doc_only=false
base_ref=""
fi
echo "skip=${skip}" >> "$GITHUB_OUTPUT"
echo "doc_only=${doc_only}" >> "$GITHUB_OUTPUT"
echo "base_ref=${base_ref}" >> "$GITHUB_OUTPUT"
# Detect which packages were touched by the PR so downstream build and test
# jobs can avoid rebuilding/retesting packages unaffected by the change.
# See issue #299.
#
# Dependency graph (verified in pyproject.toml files):
# cuda_pathfinder -> (no internal deps)
# cuda_bindings -> cuda_pathfinder
# cuda_core -> cuda_pathfinder, cuda_bindings
# cuda_python -> cuda_pathfinder, cuda_bindings, cuda_core (meta package)
#
# A change to cuda_pathfinder (or shared infra) forces a rebuild of every
# downstream module. A change to cuda_bindings forces rebuild of cuda_core.
# A change to cuda_core alone skips rebuilding/retesting cuda_bindings and
# cuda_pathfinder, but still retests the downstream cuda-python metapackage.
# Shared build/orchestration changes run the full pipeline; test-only CI
# infrastructure runs every test suite without rebuilding package wheels.
# On push to main, tag refs, schedule, or workflow_dispatch events we
# unconditionally run everything because there is no meaningful "changed
# paths" baseline for those events.
detect-changes:
if: ${{ github.repository_owner == 'nvidia' }}
runs-on: ubuntu-latest
needs: should-skip
permissions:
actions: read
contents: read
outputs:
workplan: ${{ steps.workplan.outputs.workplan }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
# Treeless clone: the commit graph is needed to resolve the PR merge
# base and classify its changed paths, but historical blobs aren't.
fetch-depth: 0
filter: blob:none
- name: Resolve PR merge base
id: merge-base
if: ${{ startsWith(github.ref_name, 'pull-request/') }}
env:
BASE_REF: ${{ needs.should-skip.outputs.base-ref }}
run: |
set -euo pipefail
if [[ -z "${BASE_REF}" ]]; then
echo "Could not resolve PR base branch" >&2
exit 1
fi
base=$(git merge-base HEAD "origin/${BASE_REF}")
echo "sha=${base}" >> "$GITHUB_OUTPUT"
- name: Resolve reusable base artifacts
id: baseline
if: ${{ startsWith(github.ref_name, 'pull-request/') }}
env:
BASE_REF: ${{ needs.should-skip.outputs.base-ref }}
MERGE_BASE: ${{ steps.merge-base.outputs.sha }}
GH_TOKEN: ${{ github.token }}
run: |
set -uo pipefail
unavailable() {
echo "No complete reusable artifact set was found; this run will build and test everything." >> "$GITHUB_STEP_SUMMARY"
exit 0
}
if [[ -z "${BASE_REF}" ]]; then
unavailable
fi
merge_base="${MERGE_BASE}"
if [[ -z "${merge_base}" ]]; then
unavailable
fi
if ! runs=$(gh run list \
--repo "${{ github.repository }}" \
--branch "${BASE_REF}" \
--commit "${merge_base}" \
--event push \
--workflow ci.yml \
--status success \
--limit 1 \
--json databaseId,headSha); then
unavailable
fi
# Reuse only artifacts produced from the exact commit used as the
# PR diff base. Using the latest base-branch run is unsafe for a PR
# that was opened before newer changes landed on that branch.
run_id=$(jq -r '.[0].databaseId // empty' <<< "$runs")
run_sha=$(jq -r '.[0].headSha // empty' <<< "$runs")
if [[ -z "${run_id}" || "${run_sha}" != "${merge_base}" ]]; then
unavailable
fi
if ! artifact_names=$(gh api \
"repos/${{ github.repository }}/actions/runs/${run_id}/artifacts?per_page=100" \
--paginate \
--jq '.artifacts[] | select(.expired == false) | .name'); then
unavailable
fi
has_artifact() {
grep -Fxq "$1" <<< "$artifact_names"
}
missing=()
for name in cuda-pathfinder-wheel cuda-python-wheel; do
has_artifact "$name" || missing+=("$name")
done
cuda_version=$(yq '.cuda.build.version' ci/versions.yml)
if ! python_versions=$(yq -r '.jobs.build.strategy.matrix."python-version"[]' .github/workflows/build-wheel.yml); then
unavailable
fi
if ! platforms=$(yq -r '.platforms[]' ci/test-matrix.yml); then
unavailable
fi
if [[ -z "${python_versions}" || -z "${platforms}" ]]; then
unavailable
fi
while IFS= read -r python_version; do
python=${python_version//./}
while IFS= read -r platform; do
binding="cuda-bindings-python${python}-cuda${cuda_version}-${platform}-${merge_base}"
core="cuda-core-python${python}-${platform}-${merge_base}"
has_artifact "$binding" || missing+=("$binding")
has_artifact "$core" || missing+=("$core")
done <<< "${platforms}"
done <<< "${python_versions}"
if (( ${#missing[@]} != 0 )); then
printf 'Missing reusable artifact: %s\n' "${missing[@]}" >&2
unavailable
fi
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
{
echo
echo "Reusable artifacts: run \`${run_id}\` at \`${merge_base}\` on \`${BASE_REF}\`."
} >> "$GITHUB_STEP_SUMMARY"
- name: Test CI workplan planner
run: python3 -m unittest ci/tools/tests/test_compute_ci_plan.py
- name: Compute CI workplan
id: workplan
env:
MERGE_BASE: ${{ steps.merge-base.outputs.sha }}
BASELINE_RUN_ID: ${{ steps.baseline.outputs.run_id }}
run: |
set -euo pipefail
workplan=$(python3 ci/tools/compute_ci_plan.py \
--merge-base "$MERGE_BASE" \
--baseline-run-id "$BASELINE_RUN_ID")
echo "workplan=$workplan" >> "$GITHUB_OUTPUT"
{
echo
echo "### CI workplan"
echo '```json'
jq . <<< "$workplan"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
api-check-core-vs-release:
name: API check (cuda_core vs. latest release)
if: >-
${{ !fromJSON(needs.should-skip.outputs.skip) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.core_api_checks }}
runs-on: ubuntu-latest
needs:
- should-skip
- detect-changes
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
filter: blob:none
- name: Find latest release tag
id: latest-tag
shell: bash --noprofile --norc -euo pipefail {0}
env:
GH_TOKEN: ${{ github.token }}
run: |
# --paginate fetches all pages; jq outputs one name per line per page;
# sed prints the first (newest) match while consuming all pages, so
# gh can complete without SIGPIPE. Fails if no cuda-core-v* tag is found.
tag="$(gh api "repos/$GITHUB_REPOSITORY/tags" --paginate \
--jq '.[] | select(.name | startswith("cuda-core-v")) | .name' \
| sed -n '1p')"
if [[ -z "${tag}" ]]; then
echo "::error::No cuda-core-v* tag found in the repository." >&2
exit 1
fi
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
- name: Fetch release tag
shell: bash --noprofile --norc -euo pipefail {0}
run: |
git fetch --depth=1 --filter=blob:none origin \
"refs/tags/${{ steps.latest-tag.outputs.tag }}:refs/tags/${{ steps.latest-tag.outputs.tag }}"
- name: Check cuda_core public API
id: griffe
uses: ./.github/actions/griffe-api-check
with:
package-name: cuda.core
package-dir: cuda_core
merge-base: ${{ steps.latest-tag.outputs.tag }}
api-check-core-vs-base:
name: API check (cuda_core vs. merge base)
if: >-
${{ startsWith(github.ref_name, 'pull-request/') &&
!fromJSON(needs.should-skip.outputs.skip) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.core_api_checks }}
runs-on: ubuntu-latest
needs:
- should-skip
- detect-changes
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
filter: blob:none
- name: Fetch merge base commit
shell: bash --noprofile --norc -euo pipefail {0}
run: |
git fetch --depth=1 --filter=blob:none origin \
"${{ fromJSON(needs.detect-changes.outputs.workplan).merge_base }}"
- name: Check cuda_core public API
id: griffe
uses: ./.github/actions/griffe-api-check
with:
package-name: cuda.core
package-dir: cuda_core
merge-base: ${{ fromJSON(needs.detect-changes.outputs.workplan).merge_base }}
# NOTE: Build jobs are intentionally split by platform rather than using a single
# matrix. This lets each test job consume its platform-specific artifacts as
# soon as they are ready. ARM64 and Windows tests also wait for linux-64,
# which produces the universal pathfinder and cuda-python wheels. Keep these
# job definitions textually identical except for:
# - host-platform value
# - if: condition (build-linux-64 omits doc-only check since it's needed for docs)
build-linux-64:
needs:
- ci-vars
- should-skip
- detect-changes
strategy:
fail-fast: false
matrix:
host-platform:
- linux-64
name: Build ${{ matrix.host-platform }}, CUDA ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
if: ${{ github.repository_owner == 'nvidia' && !fromJSON(needs.should-skip.outputs.skip) }}
permissions:
actions: read
contents: read
secrets: inherit
uses: ./.github/workflows/build-wheel.yml
with:
host-platform: ${{ matrix.host-platform }}
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
prev-cuda-version: ${{ needs.ci-vars.outputs.CUDA_PREV_BUILD_VER }}
workplan: ${{ needs.detect-changes.outputs.workplan }}
# See build-linux-64 for why build jobs are split by platform.
build-linux-aarch64:
needs:
- ci-vars
- should-skip
- detect-changes
strategy:
fail-fast: false
matrix:
host-platform:
- linux-aarch64
name: Build ${{ matrix.host-platform }}, CUDA ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
if: ${{ github.repository_owner == 'nvidia' &&
!fromJSON(needs.should-skip.outputs.skip) &&
!fromJSON(needs.should-skip.outputs.doc-only) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.platforms.linux }}
permissions:
actions: read
contents: read
secrets: inherit
uses: ./.github/workflows/build-wheel.yml
with:
host-platform: ${{ matrix.host-platform }}
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
prev-cuda-version: ${{ needs.ci-vars.outputs.CUDA_PREV_BUILD_VER }}
workplan: ${{ needs.detect-changes.outputs.workplan }}
# See build-linux-64 for why build jobs are split by platform.
build-windows:
needs:
- ci-vars
- should-skip
- detect-changes
strategy:
fail-fast: false
matrix:
host-platform:
- win-64
name: Build ${{ matrix.host-platform }}, CUDA ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
if: ${{ github.repository_owner == 'nvidia' &&
!fromJSON(needs.should-skip.outputs.skip) &&
!fromJSON(needs.should-skip.outputs.doc-only) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.platforms.windows }}
permissions:
actions: read
contents: read
secrets: inherit
uses: ./.github/workflows/build-wheel.yml
with:
host-platform: ${{ matrix.host-platform }}
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
prev-cuda-version: ${{ needs.ci-vars.outputs.CUDA_PREV_BUILD_VER }}
workplan: ${{ needs.detect-changes.outputs.workplan }}
# NOTE: test-sdist jobs are split by platform (mirroring build-* and test-wheel-*)
# so platform-specific sources (e.g. cuda_bindings/*_windows.pyx selected by
# build_hooks.py) are exercised on their target OS. Keep these job definitions
# textually identical except for:
# - host-platform value
# - uses: (test-sdist-linux.yml vs test-sdist-windows.yml)
test-sdist-linux:
needs:
- ci-vars
- should-skip
- detect-changes
- build-linux-64
name: Test sdist linux-64
if: ${{ github.repository_owner == 'nvidia' &&
!fromJSON(needs.should-skip.outputs.skip) &&
!fromJSON(needs.should-skip.outputs.doc-only) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.sdist_tests }}
permissions:
actions: read
contents: read
secrets: inherit
uses: ./.github/workflows/test-sdist-linux.yml
with:
host-platform: linux-64
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
workplan: ${{ needs.detect-changes.outputs.workplan }}
# See test-sdist-linux for why sdist test jobs are split by platform.
test-sdist-windows:
needs:
- ci-vars
- should-skip
- detect-changes
- build-linux-64
- build-windows
name: Test sdist win-64
if: ${{ github.repository_owner == 'nvidia' &&
!fromJSON(needs.should-skip.outputs.skip) &&
!fromJSON(needs.should-skip.outputs.doc-only) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.sdist_tests }}
permissions:
actions: read
contents: read
secrets: inherit
uses: ./.github/workflows/test-sdist-windows.yml
with:
host-platform: win-64
cuda-version: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
workplan: ${{ needs.detect-changes.outputs.workplan }}
# NOTE: Test jobs are split by platform for the same reason as build jobs (see
# build-linux-64). Keep these job definitions textually identical except for:
# - host-platform value
# - build job under needs:
# - uses: (test-wheel-linux.yml vs test-wheel-windows.yml)
test-linux-64:
strategy:
fail-fast: false
matrix:
host-platform:
- linux-64
name: Test ${{ matrix.host-platform }}
if: ${{ github.repository_owner == 'nvidia' &&
!fromJSON(needs.should-skip.outputs.doc-only) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.platforms.linux }}
permissions:
actions: read
contents: read # This is required for actions/checkout
needs:
- ci-vars
- should-skip
- detect-changes
- build-linux-64
secrets: inherit
uses: ./.github/workflows/test-wheel-linux.yml
with:
build-type: pull-request
host-platform: ${{ matrix.host-platform }}
build-ctk-ver: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
nruns: ${{ (github.event_name == 'schedule' && 5) || 1}}
workplan: ${{ needs.detect-changes.outputs.workplan }}
# See test-linux-64 for why test jobs are split by platform.
test-linux-aarch64:
strategy:
fail-fast: false
matrix:
host-platform:
- linux-aarch64
name: Test ${{ matrix.host-platform }}
if: ${{ github.repository_owner == 'nvidia' &&
!fromJSON(needs.should-skip.outputs.doc-only) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.platforms.linux }}
permissions:
actions: read
contents: read # This is required for actions/checkout
needs:
- ci-vars
- should-skip
- detect-changes
- build-linux-64
- build-linux-aarch64
secrets: inherit
uses: ./.github/workflows/test-wheel-linux.yml
with:
build-type: pull-request
host-platform: ${{ matrix.host-platform }}
build-ctk-ver: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
nruns: ${{ (github.event_name == 'schedule' && 5) || 1}}
workplan: ${{ needs.detect-changes.outputs.workplan }}
# See test-linux-64 for why test jobs are split by platform.
test-windows:
strategy:
fail-fast: false
matrix:
host-platform:
- win-64
name: Test ${{ matrix.host-platform }}
if: ${{ github.repository_owner == 'nvidia' &&
!fromJSON(needs.should-skip.outputs.doc-only) &&
fromJSON(needs.detect-changes.outputs.workplan).jobs.platforms.windows }}
permissions:
actions: read
contents: read # This is required for actions/checkout
needs:
- ci-vars
- should-skip
- detect-changes
- build-linux-64
- build-windows
secrets: inherit
uses: ./.github/workflows/test-wheel-windows.yml
with:
build-type: pull-request
host-platform: ${{ matrix.host-platform }}
build-ctk-ver: ${{ needs.ci-vars.outputs.CUDA_BUILD_VER }}
nruns: ${{ (github.event_name == 'schedule' && 5) || 1}}
workplan: ${{ needs.detect-changes.outputs.workplan }}
doc:
name: Docs
if: ${{ github.repository_owner == 'nvidia' }}
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
id-token: write
contents: write
pull-requests: write
needs:
- ci-vars
- build-linux-64
secrets: inherit
uses: ./.github/workflows/build-docs.yml
with:
is-release: ${{ github.ref_type == 'tag' }}
precommit-windows:
name: Pre-commit on Windows
runs-on: windows-latest
if: ${{ github.repository_owner == 'nvidia' && !fromJSON(needs.should-skip.outputs.skip) }}
needs:
- should-skip
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: '3.13'
- name: Install pre-commit
shell: bash
run: |
set -euxo pipefail
python -m pip install --upgrade pip pre-commit
- name: Run pre-commit
shell: bash
run: |
set -euxo pipefail
SKIP=lychee pre-commit run --all-files
checks:
name: Check job status
if: ${{ always() && github.repository_owner == 'nvidia' }}
runs-on: ubuntu-latest
needs:
- ci-vars
- should-skip
- detect-changes
- build-linux-64
- build-linux-aarch64
- build-windows
- test-sdist-linux
- test-sdist-windows
- test-linux-64
- test-linux-aarch64
- test-windows
- api-check-core-vs-release
- api-check-core-vs-base
- doc
- precommit-windows
steps:
- name: Exit
env:
NEEDS_JSON: ${{ toJSON(needs) }}
run: |
# GitHub treats `result == 'skipped'` as success for required
# status checks (see CCCL gate comment + cccl#605). The previous
# `cancelled || failure` predicate let upstream build failures
# propagate as `skipped` on downstream test jobs and silently
# pass this aggregator. Adopt CCCL's `check_result` pattern:
# require an explicit `expected` status per dependency, where
# anything else (including `skipped` from a failed upstream)
# fails the gate. `if: always()` on the job still ensures this
# step runs even when needs are skipped.
if [[ "${{ needs.should-skip.outputs.skip }}" == "true" ]]; then
echo "[no-ci] - skipping aggregator checks"
exit 0
fi
doc_only="${{ needs.should-skip.outputs.doc-only }}"
linux_selected="${{ needs.detect-changes.outputs.workplan && fromJSON(needs.detect-changes.outputs.workplan).jobs.platforms.linux || false }}"
windows_selected="${{ needs.detect-changes.outputs.workplan && fromJSON(needs.detect-changes.outputs.workplan).jobs.platforms.windows || false }}"
build_selected="${{ needs.detect-changes.outputs.workplan && fromJSON(needs.detect-changes.outputs.workplan).jobs.sdist_tests || false }}"
run_core_api_check="${{ needs.detect-changes.outputs.workplan && fromJSON(needs.detect-changes.outputs.workplan).jobs.core_api_checks || false }}"
is_pr="${{ startsWith(github.ref_name, 'pull-request/') }}"
status="success"
check_result() {
local name=$1 expected=$2 result
result=$(jq -r --arg name "$name" '.[$name].result // "missing"' <<< "$NEEDS_JSON")
echo "Checking $name: result='$result' (expected '$expected')"
if [[ "$result" != "$expected" ]]; then
echo "::error::$name did not match expected result"
status="failed"
fi
}
# Control jobs, the universal linux build, docs, and Windows
# pre-commit checks always run.
check_result "ci-vars" "success"
check_result "should-skip" "success"
check_result "detect-changes" "success"
check_result "build-linux-64" "success"
check_result "doc" "success"
check_result "precommit-windows" "success"
# Optional platform builds and wheel tests share the platform plan.
linux_expected="skipped"
if [[ "$doc_only" != "true" && "$linux_selected" == "true" ]]; then
linux_expected="success"
fi
windows_expected="skipped"
if [[ "$doc_only" != "true" && "$windows_selected" == "true" ]]; then
windows_expected="success"
fi
check_result "build-linux-aarch64" "$linux_expected"
check_result "build-windows" "$windows_expected"
# Sdist tests follow build selection; wheel tests follow the platform plan.
expected="skipped"
if [[ "$doc_only" != "true" && "$build_selected" == "true" ]]; then
expected="success"
fi
check_result "test-sdist-linux" "$expected"
check_result "test-sdist-windows" "$expected"
check_result "test-linux-64" "$linux_expected"
check_result "test-linux-aarch64" "$linux_expected"
check_result "test-windows" "$windows_expected"
# API compatibility checks run for cuda_core source changes and for
# conservative full runs when reusable base artifacts are unavailable.
expected="skipped"
if [[ "$run_core_api_check" == "true" ]]; then expected="success"; fi
check_result "api-check-core-vs-release" "$expected"
expected="skipped"
if [[ "$is_pr" == "true" && "$run_core_api_check" == "true" ]]; then expected="success"; fi
check_result "api-check-core-vs-base" "$expected"
[[ "$status" == "success" ]]