From c3c5bdbff1fadd420c2290cd18e25f0ca2343418 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 12:56:29 -0500 Subject: [PATCH 01/10] ci: split C++ gtests into routing and mathopt jobs Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/pr.yaml | 416 +----------------------------------- .github/workflows/test.yaml | 24 ++- ci/run_ctests.sh | 14 ++ ci/test_cpp.sh | 32 ++- ci/test_cpp_mathopt.sh | 9 + ci/test_cpp_routing.sh | 9 + 6 files changed, 81 insertions(+), 423 deletions(-) create mode 100755 ci/test_cpp_mathopt.sh create mode 100755 ci/test_cpp_routing.sh diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 37ebf57467..959314e61a 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -23,25 +23,7 @@ jobs: - checks - conda-cpp-build - conda-cpp-tests - - java-build - - java-static-build-matrix - - java-static-build - - java-static-test - - conda-python-build - - conda-python-tests - - docs-build - - docs-build-matrix - - multi-gpu-cpp-tests - - wheel-build-libcuopt - - wheel-build-libcuopt-client - - wheel-build-libcuopt-mathopt - - wheel-build-libcuopt-routing - - wheel-build-cuopt - - wheel-tests-cuopt - - wheel-build-cuopt-server - - wheel-tests-cuopt-server - - wheel-build-cuopt-sh-client - - test-self-hosted-server + - conda-cpp-tests-routing permissions: contents: read uses: rapidsai/shared-workflows/.github/workflows/pr-builder.yaml@main @@ -72,7 +54,6 @@ jobs: echo "cuopt_server_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER|split(\".\")|map(tonumber)|.[0]) | map(max_by([(.PY_VER|split(\".\")|map(tonumber)), (.CUDA_VER|split(\".\")|map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_server_test_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER | split(\".\") | map(tonumber) | .[0]) | map(max_by([(.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_sh_client_filter=[map(select(.ARCH == \"amd64\")) | min_by((.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(-tonumber)))]" >> $GITHUB_OUTPUT - changed-files: permissions: actions: read @@ -411,7 +392,7 @@ jobs: if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp with: build_type: pull-request - script: ci/test_cpp.sh + script: ci/test_cpp_mathopt.sh secrets: script-env-secret-1-key: CUOPT_S3_URI script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} @@ -419,7 +400,7 @@ jobs: script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} - multi-gpu-cpp-tests: + conda-cpp-tests-routing: needs: [conda-cpp-build, changed-files] permissions: actions: read @@ -427,362 +408,11 @@ jobs: id-token: write packages: read pull-requests: read - uses: ./.github/workflows/multi_gpu_cpp_test.yaml + uses: rapidsai/shared-workflows/.github/workflows/conda-cpp-tests.yaml@main if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp with: build_type: pull-request - secrets: inherit # zizmor: ignore[secrets-inherit] - conda-python-build: - needs: [build-details, conda-cpp-build, changed-files] - # Consumed by conda-python-tests and docs-build. - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda || - fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/conda-python-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_python.sh - # Build a conda package for each CUDA x ARCH x minimum supported Python version - matrix_filter: group_by({CUDA_VER, ARCH}) | map(min_by(.PY_VER | split(".") | map(tonumber))) - conda-python-tests: - needs: [conda-python-build, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - uses: rapidsai/shared-workflows/.github/workflows/conda-python-tests.yaml@main - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda - with: - build_type: pull-request - run_codecov: false - script: ci/test_python.sh - docs-build-matrix: - permissions: - contents: read - uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main - with: - build_type: pull-request - matrix_name: docs-build - docs-build: - needs: [docs-build-matrix, conda-python-build, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.docs-build-matrix.outputs.matrix) }} - if: fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs - with: - build_type: pull-request - node_type: "gpu-${{ matrix.GPU }}-${{ matrix.DRIVER }}-1" - arch: "${{ matrix.ARCH }}" - file_to_upload: "docs/cuopt/build/html/" - artifact-name: "cuopt_docs" - container_image: "rapidsai/ci-conda:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" - script: "ci/build_docs.sh" - # Compiles libcuopt from source (one self-contained classifier JAR per CUDA major and - # architecture), so this does not need conda-cpp-build. See #1817. - java-static-build-matrix: - needs: changed-files - permissions: - contents: read - uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || - fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp - with: - build_type: pull-request - matrix_name: conda-cpp-build - matrix_filter: 'map(. + {CUDA_MAJOR: (.CUDA_VER | split(".") | .[0])}) | unique_by([.ARCH, .CUDA_MAJOR])' - - java-static-build: - needs: [java-static-build-matrix, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || - fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp - with: - build_type: pull-request - node_type: "cpu16" - arch: ${{ matrix.ARCH }} - # ci-wheel (Rocky 8) rather than ci-conda: gcc-toolset-14 on Rocky 8 produces a libstdc++ - # ABI requirement the RAPIDS-supported platforms can actually satisfy, unlike ci-conda's - # gcc_linux-64 conda package -- the same fix cuDF applied in rapidsai/cudf#23766 after - # hitting this in production (rapidsai/cudf#23753). See setup_java_static_env.sh. - # - # Must be CUDA-version-pinned, not the bare "26.10-latest" tag: custom-job.yaml has no - # per-matrix env passthrough, so an untagged image would leave RAPIDS_CUDA_VERSION at - # that image's single baked-in default for every matrix entry. - # ci/build_java_static.sh reads it to pick the CUDA toolkit, so every "cuN" classifier - # JAR would actually be built against the same CUDA version and just mislabeled. Matches - # the pattern java-static-test (test.yaml) already uses for this image family. - container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" - script: "ci/build_java_static.sh" - artifact-name: "cuopt_java_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" - file_to_upload: "java/cuopt/classifier-jars/" - - # Runs the full Java suite against each classifier JAR on a GPU, with no libcuopt installed, - # so a JAR that loads but computes wrong answers fails here rather than at a user. - java-static-test: - needs: [java-static-build, java-static-build-matrix] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} - with: - build_type: pull-request - node_type: "gpu-l4-latest-1" - arch: ${{ matrix.ARCH }} - # A plain CUDA-devel + dnf environment rather than rapidsai/ci-conda: the packaged JAR - # only needs a JDK, Maven and the CUDA runtime (libcublas/libcusparse, already in this - # image) to test, and a fresh `conda create` every run was slow enough that concurrent - # matrix jobs' cold Maven Central resolution reliably lined up and triggered 429s. - container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" - script: "ci/test_java_static.sh" - # Surefire fork-crash diagnostics (dumpstream/hs_err files) are also printed inline by - # the script on failure, but keep the raw reports downloadable too -- the JVM sometimes - # crashes without a clean dumpstream, and per-matrix-entry artifacts survive independently - # of how much of the console log GitHub keeps. - artifact-name: "cuopt_java_static_test_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" - file_to_upload: "java/cuopt/target/surefire-reports/" - - java-build: - needs: [conda-cpp-build, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || - fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp - with: - build_type: pull-request - node_type: "gpu-l4-latest-1" - arch: "amd64" - container_image: "rapidsai/ci-conda:26.12-latest" - script: "ci/test_java.sh" - artifact-name: "cuopt-java" - file_to_upload: "java/cuopt/target/" - wheel-build-libcuopt-client: - needs: [build-details, compute-matrix-filters, changed-files] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_client_filter }} - package-type: cpp - package-name: libcuopt_client - # The wheel name carries no CUDA suffix, so neither should the artifact. - append-cuda-suffix: false - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt_client.sh - wheel-build-libcuopt-mathopt: - needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - # Same filter as libcuopt: every arch and CUDA version, latest Python only. - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} - package-type: cpp - package-name: libcuopt_mathopt - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt_mathopt.sh - wheel-build-libcuopt-routing: - needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - # Same filter as libcuopt: every arch and CUDA version, latest Python only. - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} - package-type: cpp - package-name: libcuopt_routing - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt_routing.sh - wheel-build-libcuopt: - needs: - - build-details - - compute-matrix-filters - - changed-files - - wheel-build-libcuopt-client - - wheel-build-libcuopt-mathopt - - wheel-build-libcuopt-routing - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - # build for every combination of arch and CUDA version, but only for the latest Python - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} - package-type: cpp - package-name: libcuopt - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt.sh - wheel-build-cuopt: - needs: - - build-details - - wheel-build-libcuopt - - wheel-build-libcuopt-client - - wheel-build-libcuopt-mathopt - - wheel-build-libcuopt-routing - - compute-matrix-filters - - changed-files - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_cuopt.sh - package-name: cuopt - package-type: python - # Build a wheel for each CUDA x ARCH x minimum supported Python version - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_filter }} - wheel-tests-cuopt: - needs: [wheel-build-cuopt, wheel-build-cuopt-sh-client, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - with: - build_type: pull-request - script: ci/test_wheel_cuopt.sh - secrets: - script-env-secret-1-key: CUOPT_S3_URI - script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} - script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID - script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} - script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY - script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} - wheel-build-cuopt-server: - needs: [build-details, checks, compute-matrix-filters, changed-files] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_cuopt_server.sh - package-name: cuopt_server - package-type: python - pure-wheel: true - # Only need 1 package per CUDA major version. This selects "ARCH=amd64 + the latest supported Python, 1 job per major CUDA version". - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_filter }} - wheel-build-cuopt-sh-client: - needs: [build-details, compute-matrix-filters, changed-files] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_cuopt_sh_client.sh - package-name: cuopt_sh_client - package-type: python - append-cuda-suffix: false - pure-wheel: true - # only need 1 build (noarch package): this selects amd64, oldest-supported Python, latest-supported CUDA - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_sh_client_filter }} - wheel-tests-cuopt-server: - needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files, compute-matrix-filters] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - with: - build_type: pull-request - script: ci/test_wheel_cuopt_server.sh - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_test_filter }} + script: ci/test_cpp_routing.sh secrets: script-env-secret-1-key: CUOPT_S3_URI script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} @@ -790,39 +420,3 @@ jobs: script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} - test-self-hosted-server: - needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: ./.github/workflows/self_hosted_service_test.yaml - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - with: - build_type: pull-request - script: ci/test_self_hosted_service.sh - pr-test-summary: - name: "PR test summary (non-blocking)" - needs: - - conda-cpp-tests - - conda-python-tests - - wheel-tests-cuopt - - wheel-tests-cuopt-server - - test-self-hosted-server - if: always() - runs-on: ubuntu-latest - permissions: - actions: read - pull-requests: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - sparse-checkout: ci/utils/pr_test_summary.py - sparse-checkout-cone-mode: false - - run: python3 ci/utils/pr_test_summary.py - env: - GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1e640721e7..1d4f0e6139 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -41,7 +41,29 @@ jobs: branch: ${{ inputs.branch }} date: ${{ inputs.date }} sha: ${{ inputs.sha }} - script: ci/test_cpp.sh + script: ci/test_cpp_mathopt.sh + secrets: + script-env-secret-1-key: CUOPT_S3_URI + script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} + script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID + script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} + script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY + script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} + + conda-cpp-tests-routing: + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: rapidsai/shared-workflows/.github/workflows/conda-cpp-tests.yaml@main + with: + build_type: ${{ inputs.build_type }} + branch: ${{ inputs.branch }} + date: ${{ inputs.date }} + sha: ${{ inputs.sha }} + script: ci/test_cpp_routing.sh secrets: script-env-secret-1-key: CUOPT_S3_URI script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} diff --git a/ci/run_ctests.sh b/ci/run_ctests.sh index cb6662af07..79aec6ee31 100755 --- a/ci/run_ctests.sh +++ b/ci/run_ctests.sh @@ -14,6 +14,8 @@ # GTEST_OUTPUT - gtest XML output prefix (set by test_cpp.sh) # GTEST_MAX_RETRIES - max retries per failing test case (default: 2) # RAPIDS_TESTS_DIR - directory for test results +# CUOPT_CPP_TEST_GROUP - which binaries to run: all (default), routing +# (ROUTING_* only) or mathopt (everything except ROUTING_*) set -euo pipefail @@ -212,7 +214,19 @@ run_gtest_with_retry() { return 0 } +CUOPT_CPP_TEST_GROUP="${CUOPT_CPP_TEST_GROUP:-all}" +case "${CUOPT_CPP_TEST_GROUP}" in + all | routing | mathopt) ;; + *) echo "Error: invalid CUOPT_CPP_TEST_GROUP '${CUOPT_CPP_TEST_GROUP}'" >&2; exit 1 ;; +esac + for gt in "${GTEST_DIR}"/*_TEST; do + is_routing=false + [[ "$(basename "${gt}")" == ROUTING_* ]] && is_routing=true + if [[ "${CUOPT_CPP_TEST_GROUP}" == "routing" && "${is_routing}" == false ]] || + [[ "${CUOPT_CPP_TEST_GROUP}" == "mathopt" && "${is_routing}" == true ]]; then + continue + fi run_gtest_with_retry "${gt}" "$@" || true done diff --git a/ci/test_cpp.sh b/ci/test_cpp.sh index 8f3c2c4fa7..6a1e86f0a8 100755 --- a/ci/test_cpp.sh +++ b/ci/test_cpp.sh @@ -34,16 +34,23 @@ rapids-print-env rapids-logger "Check GPU usage" nvidia-smi -rapids-logger "Download datasets" -./datasets/linear_programming/download_pdlp_test_dataset.sh -./datasets/mip/download_miplib_test_dataset.sh -./datasets/quadratic_programming/download_qplib_test_dataset.sh - -RAPIDS_DATASET_ROOT_DIR="$(realpath datasets)" -export RAPIDS_DATASET_ROOT_DIR -pushd "${RAPIDS_DATASET_ROOT_DIR}" -./get_test_data.sh -popd +# CUOPT_CPP_TEST_GROUP: all (default), routing or mathopt; see run_ctests.sh +CUOPT_CPP_TEST_GROUP="${CUOPT_CPP_TEST_GROUP:-all}" +export CUOPT_CPP_TEST_GROUP + +# Routing tests do not use the LP/MIP/QP datasets. +if [[ "${CUOPT_CPP_TEST_GROUP}" != "routing" ]]; then + rapids-logger "Download datasets" + ./datasets/linear_programming/download_pdlp_test_dataset.sh + ./datasets/mip/download_miplib_test_dataset.sh + ./datasets/quadratic_programming/download_qplib_test_dataset.sh + + RAPIDS_DATASET_ROOT_DIR="$(realpath datasets)" + export RAPIDS_DATASET_ROOT_DIR + pushd "${RAPIDS_DATASET_ROOT_DIR}" + ./get_test_data.sh + popd +fi EXITCODE=0 FAILED_STEPS=() @@ -66,7 +73,10 @@ run_step_with_timeout "gtests (run_ctests.sh)" 90m "" \ rapids-logger "Generate nightly test report" source "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/utils/nightly_report_helper.sh" -generate_nightly_report "cpp" +# Separate report type per group so routing/mathopt do not share S3 history. +REPORT_TYPE="cpp" +[[ "${CUOPT_CPP_TEST_GROUP}" != "all" ]] && REPORT_TYPE="cpp-${CUOPT_CPP_TEST_GROUP}" +generate_nightly_report "${REPORT_TYPE}" if [ "${#FAILED_STEPS[@]}" -gt 0 ]; then EXITCODE=1 diff --git a/ci/test_cpp_mathopt.sh b/ci/test_cpp_mathopt.sh new file mode 100755 index 0000000000..6267f8e60b --- /dev/null +++ b/ci/test_cpp_mathopt.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +export CUOPT_CPP_TEST_GROUP=mathopt +exec "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/test_cpp.sh" "$@" diff --git a/ci/test_cpp_routing.sh b/ci/test_cpp_routing.sh new file mode 100755 index 0000000000..72164d713f --- /dev/null +++ b/ci/test_cpp_routing.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +export CUOPT_CPP_TEST_GROUP=routing +exec "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/test_cpp.sh" "$@" From cfab996ca2a96700af69e1eda2fd204b6c2ca452 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 16:09:37 -0500 Subject: [PATCH 02/10] ci: rename conda-cpp-tests job to conda-cpp-tests-mathopt Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/pr.yaml | 4 ++-- .github/workflows/test.yaml | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 959314e61a..f5a53a0c15 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -22,7 +22,7 @@ jobs: - changed-files - checks - conda-cpp-build - - conda-cpp-tests + - conda-cpp-tests-mathopt - conda-cpp-tests-routing permissions: contents: read @@ -380,7 +380,7 @@ jobs: build_type: pull-request build-datetime: ${{ needs.build-details.outputs.build-datetime }} script: ci/build_cpp.sh - conda-cpp-tests: + conda-cpp-tests-mathopt: needs: [conda-cpp-build, changed-files] permissions: actions: read diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1d4f0e6139..ef4e02f1c1 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -28,7 +28,7 @@ on: permissions: {} jobs: - conda-cpp-tests: + conda-cpp-tests-mathopt: permissions: actions: read contents: read @@ -275,7 +275,8 @@ jobs: contents: read if: ${{ always() && inputs.build_type == 'nightly' }} needs: - - conda-cpp-tests + - conda-cpp-tests-mathopt + - conda-cpp-tests-routing - conda-python-tests - conda-java-tests - java-static-test From f4b7001ca9933b5632cf5c4de8ff9bfee754eefb Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 16:10:20 -0500 Subject: [PATCH 03/10] ci: keep the cpp report type for mathopt to preserve test history Co-Authored-By: Claude Sonnet 5.5 --- ci/test_cpp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/test_cpp.sh b/ci/test_cpp.sh index 6a1e86f0a8..60dc6d535d 100755 --- a/ci/test_cpp.sh +++ b/ci/test_cpp.sh @@ -73,9 +73,9 @@ run_step_with_timeout "gtests (run_ctests.sh)" 90m "" \ rapids-logger "Generate nightly test report" source "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/utils/nightly_report_helper.sh" -# Separate report type per group so routing/mathopt do not share S3 history. +# Only routing gets its own report type; "cpp" keeps the existing flaky/failure history. REPORT_TYPE="cpp" -[[ "${CUOPT_CPP_TEST_GROUP}" != "all" ]] && REPORT_TYPE="cpp-${CUOPT_CPP_TEST_GROUP}" +[[ "${CUOPT_CPP_TEST_GROUP}" == "routing" ]] && REPORT_TYPE="cpp-routing" generate_nightly_report "${REPORT_TYPE}" if [ "${#FAILED_STEPS[@]}" -gt 0 ]; then From e12f861678fc3ae0dae39daef4c6654bf3d4c1aa Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 16:45:29 -0500 Subject: [PATCH 04/10] ci: use separate cpp-mathopt and cpp-routing report types Co-Authored-By: Claude Sonnet 5.5 --- ci/test_cpp.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/test_cpp.sh b/ci/test_cpp.sh index 60dc6d535d..a44bba8e9b 100755 --- a/ci/test_cpp.sh +++ b/ci/test_cpp.sh @@ -73,9 +73,9 @@ run_step_with_timeout "gtests (run_ctests.sh)" 90m "" \ rapids-logger "Generate nightly test report" source "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/utils/nightly_report_helper.sh" -# Only routing gets its own report type; "cpp" keeps the existing flaky/failure history. +# Separate report type per group so routing/mathopt keep separate history. REPORT_TYPE="cpp" -[[ "${CUOPT_CPP_TEST_GROUP}" == "routing" ]] && REPORT_TYPE="cpp-routing" +[[ "${CUOPT_CPP_TEST_GROUP}" != "all" ]] && REPORT_TYPE="cpp-${CUOPT_CPP_TEST_GROUP}" generate_nightly_report "${REPORT_TYPE}" if [ "${#FAILED_STEPS[@]}" -gt 0 ]; then From 872d420f8ae3a7184dd38c762ec391cedf3cdab6 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 16:46:48 -0500 Subject: [PATCH 05/10] ci: restore full pr.yaml with the routing and mathopt cpp test jobs Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/pr.yaml | 456 +++++++++++++++++++++++++++++++++++++- 1 file changed, 454 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index f5a53a0c15..19f4f11de3 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -24,6 +24,25 @@ jobs: - conda-cpp-build - conda-cpp-tests-mathopt - conda-cpp-tests-routing + - java-build + - java-static-build-matrix + - java-static-build + - java-static-test + - conda-python-build + - conda-python-tests + - docs-build + - docs-build-matrix + - multi-gpu-cpp-tests + - wheel-build-libcuopt + - wheel-build-libcuopt-client + - wheel-build-libcuopt-mathopt + - wheel-build-libcuopt-routing + - wheel-build-cuopt + - wheel-tests-cuopt + - wheel-build-cuopt-server + - wheel-tests-cuopt-server + - wheel-build-cuopt-sh-client + - test-self-hosted-server permissions: contents: read uses: rapidsai/shared-workflows/.github/workflows/pr-builder.yaml@main @@ -54,6 +73,7 @@ jobs: echo "cuopt_server_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER|split(\".\")|map(tonumber)|.[0]) | map(max_by([(.PY_VER|split(\".\")|map(tonumber)), (.CUDA_VER|split(\".\")|map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_server_test_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER | split(\".\") | map(tonumber) | .[0]) | map(max_by([(.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_sh_client_filter=[map(select(.ARCH == \"amd64\")) | min_by((.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(-tonumber)))]" >> $GITHUB_OUTPUT + changed-files: permissions: actions: read @@ -67,7 +87,9 @@ jobs: - '**' - '!.ai/**' - '!.clang-format' + - '!.claude-plugin/**' - '!.coderabbit.yaml' + - '!.cursor-plugin/**' - '!.gitattributes' - '!.github/.ai/**' - '!.github/.coderabbit_review_guide.md' @@ -85,14 +107,19 @@ jobs: - '!.github/workflows/build_test_publish_images.yaml' - '!.github/workflows/cloud_ci.yaml' - '!.github/workflows/kitmaker_portal.yaml' + - '!.github/workflows/multi_gpu_cpp_test.yaml' + - '!.github/workflows/nightly-summary.yaml' - '!.github/workflows/nightly.yaml' - '!.github/workflows/request-nvskills-ci.yml' + - '!.github/workflows/self_hosted_service_test.yaml' - '!.github/workflows/test.yaml' - '!.github/workflows/test_images.yaml' - '!.github/workflows/trigger-breaking-change-alert.yaml' - '!.gitignore' - '!.pre-commit-config.yaml' - '!.yamllint.yaml' + - '!agents/**' + - '!ci/utils/pr_test_summary.py' - '!codecov.yml' - '!AGENTS.md' - '!CHANGELOG.md' @@ -117,9 +144,12 @@ jobs: - '!ci/test_wheel*.sh' - '!ci/thirdparty-testing/**' - '!container-builder/**' + - '!cpp/tests/**' + - '!gemini-extension.json' - '!helmchart/**' - '!java/**' - '!ngc/**' + - '!skills/**' - '!sonar-project.properties' - '!sonarqube/**' - '!ucf/**' @@ -149,14 +179,17 @@ jobs: - '!.github/workflows/build_test_publish_images.yaml' - '!.github/workflows/cloud_ci.yaml' - '!.github/workflows/kitmaker_portal.yaml' + - '!.github/workflows/nightly-summary.yaml' - '!.github/workflows/nightly.yaml' - '!.github/workflows/request-nvskills-ci.yml' + - '!.github/workflows/self_hosted_service_test.yaml' - '!.github/workflows/test.yaml' - '!.github/workflows/test_images.yaml' - '!.github/workflows/trigger-breaking-change-alert.yaml' - '!.gitignore' - '!.pre-commit-config.yaml' - '!.yamllint.yaml' + - '!ci/utils/pr_test_summary.py' - '!codecov.yml' - '!AGENTS.md' - '!CONTRIBUTING.md' @@ -206,8 +239,6 @@ jobs: - 'ci/test_java.sh' - 'dependencies.yaml' - '.github/workflows/pr.yaml' - - '.github/workflows/build.yaml' - - '.github/workflows/test.yaml' test_python_conda: - '**' - '!**/*.md' @@ -233,14 +264,20 @@ jobs: - '!.github/workflows/build_test_publish_images.yaml' - '!.github/workflows/cloud_ci.yaml' - '!.github/workflows/kitmaker_portal.yaml' + - '!.github/workflows/multi_gpu_cpp_test.yaml' + - '!.github/workflows/nightly-summary.yaml' - '!.github/workflows/nightly.yaml' - '!.github/workflows/request-nvskills-ci.yml' + - '!.github/workflows/self_hosted_service_test.yaml' - '!.github/workflows/test.yaml' - '!.github/workflows/test_images.yaml' - '!.github/workflows/trigger-breaking-change-alert.yaml' - '!.gitignore' - '!.pre-commit-config.yaml' - '!.yamllint.yaml' + - '!ci/run_ctests.sh' + - '!ci/test_cpp*.sh' + - '!ci/utils/pr_test_summary.py' - '!codecov.yml' - '!AGENTS.md' - '!CONTRIBUTING.md' @@ -263,6 +300,7 @@ jobs: - '!ci/utils/sync_skills_version.sh' - '!ci/utils/validate_skills.sh' - '!container-builder/**' + - '!cpp/tests/**' - '!docs/**' - '!gemini-extension.json' - '!helmchart/**' @@ -305,6 +343,8 @@ jobs: - '!.github/workflows/build_test_publish_images.yaml' - '!.github/workflows/cloud_ci.yaml' - '!.github/workflows/kitmaker_portal.yaml' + - '!.github/workflows/multi_gpu_cpp_test.yaml' + - '!.github/workflows/nightly-summary.yaml' - '!.github/workflows/nightly.yaml' - '!.github/workflows/request-nvskills-ci.yml' - '!.github/workflows/test.yaml' @@ -313,6 +353,9 @@ jobs: - '!.gitignore' - '!.pre-commit-config.yaml' - '!.yamllint.yaml' + - '!ci/test_cpp*.sh' + - '!ci/test_wheel_split_packages.sh' + - '!ci/utils/pr_test_summary.py' - '!codecov.yml' - '!AGENTS.md' - '!CONTRIBUTING.md' @@ -337,6 +380,7 @@ jobs: - '!ci/utils/validate_skills.sh' - '!conda/**' - '!container-builder/**' + - '!cpp/tests/**' - '!gemini-extension.json' - '!helmchart/**' - '!img/**' @@ -420,3 +464,411 @@ jobs: script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} + multi-gpu-cpp-tests: + needs: [conda-cpp-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: ./.github/workflows/multi_gpu_cpp_test.yaml + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + secrets: inherit # zizmor: ignore[secrets-inherit] + conda-python-build: + needs: [build-details, conda-cpp-build, changed-files] + # Consumed by conda-python-tests and docs-build. + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda || + fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/conda-python-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_python.sh + # Build a conda package for each CUDA x ARCH x minimum supported Python version + matrix_filter: group_by({CUDA_VER, ARCH}) | map(min_by(.PY_VER | split(".") | map(tonumber))) + conda-python-tests: + needs: [conda-python-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: rapidsai/shared-workflows/.github/workflows/conda-python-tests.yaml@main + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda + with: + build_type: pull-request + run_codecov: false + script: ci/test_python.sh + docs-build-matrix: + permissions: + contents: read + uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main + with: + build_type: pull-request + matrix_name: docs-build + docs-build: + needs: [docs-build-matrix, conda-python-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.docs-build-matrix.outputs.matrix) }} + if: fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs + with: + build_type: pull-request + node_type: "gpu-${{ matrix.GPU }}-${{ matrix.DRIVER }}-1" + arch: "${{ matrix.ARCH }}" + file_to_upload: "docs/cuopt/build/html/" + artifact-name: "cuopt_docs" + container_image: "rapidsai/ci-conda:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" + script: "ci/build_docs.sh" + # Compiles libcuopt from source (one self-contained classifier JAR per CUDA major and + # architecture), so this does not need conda-cpp-build. See #1817. + java-static-build-matrix: + needs: changed-files + permissions: + contents: read + uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || + fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + matrix_name: conda-cpp-build + matrix_filter: 'map(. + {CUDA_MAJOR: (.CUDA_VER | split(".") | .[0])}) | unique_by([.ARCH, .CUDA_MAJOR])' + + java-static-build: + needs: [java-static-build-matrix, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || + fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + node_type: "cpu16" + arch: ${{ matrix.ARCH }} + # ci-wheel (Rocky 8) rather than ci-conda: gcc-toolset-14 on Rocky 8 produces a libstdc++ + # ABI requirement the RAPIDS-supported platforms can actually satisfy, unlike ci-conda's + # gcc_linux-64 conda package -- the same fix cuDF applied in rapidsai/cudf#23766 after + # hitting this in production (rapidsai/cudf#23753). See setup_java_static_env.sh. + # + # Must be CUDA-version-pinned, not the bare "26.10-latest" tag: custom-job.yaml has no + # per-matrix env passthrough, so an untagged image would leave RAPIDS_CUDA_VERSION at + # that image's single baked-in default for every matrix entry. + # ci/build_java_static.sh reads it to pick the CUDA toolkit, so every "cuN" classifier + # JAR would actually be built against the same CUDA version and just mislabeled. Matches + # the pattern java-static-test (test.yaml) already uses for this image family. + container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" + script: "ci/build_java_static.sh" + artifact-name: "cuopt_java_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" + file_to_upload: "java/cuopt/classifier-jars/" + + # Runs the full Java suite against each classifier JAR on a GPU, with no libcuopt installed, + # so a JAR that loads but computes wrong answers fails here rather than at a user. + java-static-test: + needs: [java-static-build, java-static-build-matrix] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} + with: + build_type: pull-request + node_type: "gpu-l4-latest-1" + arch: ${{ matrix.ARCH }} + # A plain CUDA-devel + dnf environment rather than rapidsai/ci-conda: the packaged JAR + # only needs a JDK, Maven and the CUDA runtime (libcublas/libcusparse, already in this + # image) to test, and a fresh `conda create` every run was slow enough that concurrent + # matrix jobs' cold Maven Central resolution reliably lined up and triggered 429s. + container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" + script: "ci/test_java_static.sh" + # Surefire fork-crash diagnostics (dumpstream/hs_err files) are also printed inline by + # the script on failure, but keep the raw reports downloadable too -- the JVM sometimes + # crashes without a clean dumpstream, and per-matrix-entry artifacts survive independently + # of how much of the console log GitHub keeps. + artifact-name: "cuopt_java_static_test_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" + file_to_upload: "java/cuopt/target/surefire-reports/" + + java-build: + needs: [conda-cpp-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || + fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + node_type: "gpu-l4-latest-1" + arch: "amd64" + container_image: "rapidsai/ci-conda:26.12-latest" + script: "ci/test_java.sh" + artifact-name: "cuopt-java" + file_to_upload: "java/cuopt/target/" + wheel-build-libcuopt-client: + needs: [build-details, compute-matrix-filters, changed-files] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_client_filter }} + package-type: cpp + package-name: libcuopt_client + # The wheel name carries no CUDA suffix, so neither should the artifact. + append-cuda-suffix: false + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt_client.sh + wheel-build-libcuopt-mathopt: + needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + # Same filter as libcuopt: every arch and CUDA version, latest Python only. + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} + package-type: cpp + package-name: libcuopt_mathopt + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt_mathopt.sh + wheel-build-libcuopt-routing: + needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + # Same filter as libcuopt: every arch and CUDA version, latest Python only. + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} + package-type: cpp + package-name: libcuopt_routing + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt_routing.sh + wheel-build-libcuopt: + needs: + - build-details + - compute-matrix-filters + - changed-files + - wheel-build-libcuopt-client + - wheel-build-libcuopt-mathopt + - wheel-build-libcuopt-routing + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + # build for every combination of arch and CUDA version, but only for the latest Python + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} + package-type: cpp + package-name: libcuopt + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt.sh + wheel-build-cuopt: + needs: + - build-details + - wheel-build-libcuopt + - wheel-build-libcuopt-client + - wheel-build-libcuopt-mathopt + - wheel-build-libcuopt-routing + - compute-matrix-filters + - changed-files + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_cuopt.sh + package-name: cuopt + package-type: python + # Build a wheel for each CUDA x ARCH x minimum supported Python version + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_filter }} + wheel-tests-cuopt: + needs: [wheel-build-cuopt, wheel-build-cuopt-sh-client, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + with: + build_type: pull-request + script: ci/test_wheel_cuopt.sh + secrets: + script-env-secret-1-key: CUOPT_S3_URI + script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} + script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID + script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} + script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY + script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} + wheel-build-cuopt-server: + needs: [build-details, checks, compute-matrix-filters, changed-files] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_cuopt_server.sh + package-name: cuopt_server + package-type: python + pure-wheel: true + # Only need 1 package per CUDA major version. This selects "ARCH=amd64 + the latest supported Python, 1 job per major CUDA version". + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_filter }} + wheel-build-cuopt-sh-client: + needs: [build-details, compute-matrix-filters, changed-files] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_cuopt_sh_client.sh + package-name: cuopt_sh_client + package-type: python + append-cuda-suffix: false + pure-wheel: true + # only need 1 build (noarch package): this selects amd64, oldest-supported Python, latest-supported CUDA + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_sh_client_filter }} + wheel-tests-cuopt-server: + needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files, compute-matrix-filters] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + with: + build_type: pull-request + script: ci/test_wheel_cuopt_server.sh + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_test_filter }} + secrets: + script-env-secret-1-key: CUOPT_S3_URI + script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} + script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID + script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} + script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY + script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} + test-self-hosted-server: + needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: ./.github/workflows/self_hosted_service_test.yaml + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + with: + build_type: pull-request + script: ci/test_self_hosted_service.sh + pr-test-summary: + name: "PR test summary (non-blocking)" + needs: + - conda-cpp-tests-mathopt + - conda-cpp-tests-routing + - conda-python-tests + - wheel-tests-cuopt + - wheel-tests-cuopt-server + - test-self-hosted-server + if: always() + runs-on: ubuntu-latest + permissions: + actions: read + pull-requests: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: ci/utils/pr_test_summary.py + sparse-checkout-cone-mode: false + - run: python3 ci/utils/pr_test_summary.py + env: + GH_TOKEN: ${{ github.token }} From 2ff657bdd90424ff425ae15a415908786412b3ac Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 16:48:00 -0500 Subject: [PATCH 06/10] ci: download only the LP/MIP/QP datasets for mathopt and routing datasets for routing Co-Authored-By: Claude Sonnet 5.5 --- ci/test_cpp.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ci/test_cpp.sh b/ci/test_cpp.sh index a44bba8e9b..1349358ad4 100755 --- a/ci/test_cpp.sh +++ b/ci/test_cpp.sh @@ -38,15 +38,19 @@ nvidia-smi CUOPT_CPP_TEST_GROUP="${CUOPT_CPP_TEST_GROUP:-all}" export CUOPT_CPP_TEST_GROUP -# Routing tests do not use the LP/MIP/QP datasets. +# LP/MIP/QP datasets are for mathopt tests; get_test_data.sh fetches the routing datasets. if [[ "${CUOPT_CPP_TEST_GROUP}" != "routing" ]]; then - rapids-logger "Download datasets" + rapids-logger "Download mathopt datasets" ./datasets/linear_programming/download_pdlp_test_dataset.sh ./datasets/mip/download_miplib_test_dataset.sh ./datasets/quadratic_programming/download_qplib_test_dataset.sh +fi + +RAPIDS_DATASET_ROOT_DIR="$(realpath datasets)" +export RAPIDS_DATASET_ROOT_DIR - RAPIDS_DATASET_ROOT_DIR="$(realpath datasets)" - export RAPIDS_DATASET_ROOT_DIR +if [[ "${CUOPT_CPP_TEST_GROUP}" != "mathopt" ]]; then + rapids-logger "Download routing datasets" pushd "${RAPIDS_DATASET_ROOT_DIR}" ./get_test_data.sh popd From 6564cc2564de637448baebef626da1aaf07a7329 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 16:55:26 -0500 Subject: [PATCH 07/10] ci: select routing vs mathopt gtests by CTest label Install a .labels marker next to labeled test binaries and select on it in run_ctests.sh. Fail if a group selects no binaries. Co-Authored-By: Claude Sonnet 5.5 --- ci/run_ctests.sh | 17 +++++++++++++++-- cpp/tests/CMakeLists.txt | 9 +++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/ci/run_ctests.sh b/ci/run_ctests.sh index 79aec6ee31..68c4648001 100755 --- a/ci/run_ctests.sh +++ b/ci/run_ctests.sh @@ -15,7 +15,8 @@ # GTEST_MAX_RETRIES - max retries per failing test case (default: 2) # RAPIDS_TESTS_DIR - directory for test results # CUOPT_CPP_TEST_GROUP - which binaries to run: all (default), routing -# (ROUTING_* only) or mathopt (everything except ROUTING_*) +# (binaries labeled "routing" in cpp/tests) or mathopt +# (everything else, including unlabeled binaries) set -euo pipefail @@ -220,16 +221,28 @@ case "${CUOPT_CPP_TEST_GROUP}" in *) echo "Error: invalid CUOPT_CPP_TEST_GROUP '${CUOPT_CPP_TEST_GROUP}'" >&2; exit 1 ;; esac +# .labels is installed next to each labeled binary (see ConfigureTest). +has_label() { + [[ -f "$1.labels" ]] && grep -qx "$2" "$1.labels" +} + +NUM_RUN=0 for gt in "${GTEST_DIR}"/*_TEST; do is_routing=false - [[ "$(basename "${gt}")" == ROUTING_* ]] && is_routing=true + has_label "${gt}" routing && is_routing=true if [[ "${CUOPT_CPP_TEST_GROUP}" == "routing" && "${is_routing}" == false ]] || [[ "${CUOPT_CPP_TEST_GROUP}" == "mathopt" && "${is_routing}" == true ]]; then continue fi + NUM_RUN=$((NUM_RUN + 1)) run_gtest_with_retry "${gt}" "$@" || true done +if [ "${NUM_RUN}" -eq 0 ]; then + echo "Error: no gtest binaries selected for group '${CUOPT_CPP_TEST_GROUP}' in ${GTEST_DIR}" >&2 + OVERALL_RC=1 +fi + # Final summary so failures are easy to spot in the raw run log. # nightly_report.py also produces a structured report from the XML files, # but this prints early (before any post-test-script steps) and surfaces diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 76db000434..0383138593 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -126,6 +126,15 @@ function(ConfigureTest CMAKE_TEST_NAME) rapids_test_add(NAME ${CMAKE_TEST_NAME} COMMAND ${CMAKE_TEST_NAME} INSTALL_COMPONENT_SET testing) if(CT_LABELS) set_tests_properties(${CMAKE_TEST_NAME} PROPERTIES LABELS "${CT_LABELS}") + # Installed next to the binary so ci/run_ctests.sh can select tests by label. + string(REPLACE ";" "\n" CT_LABELS_TEXT "${CT_LABELS}") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_TEST_NAME}.labels" "${CT_LABELS_TEXT}\n") + install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_TEST_NAME}.labels" + COMPONENT testing + DESTINATION bin/gtests/libcuopt + EXCLUDE_FROM_ALL + ) endif() install( TARGETS ${CMAKE_TEST_NAME} From c72b928faf979e6c3f8845273bc659c320c3e4b4 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 16:55:39 -0500 Subject: [PATCH 08/10] TEMP: trim pr.yaml to cpp build and tests while testing the split Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/pr.yaml | 428 -------------------------------------- 1 file changed, 428 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 19f4f11de3..60068c83ea 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -24,25 +24,6 @@ jobs: - conda-cpp-build - conda-cpp-tests-mathopt - conda-cpp-tests-routing - - java-build - - java-static-build-matrix - - java-static-build - - java-static-test - - conda-python-build - - conda-python-tests - - docs-build - - docs-build-matrix - - multi-gpu-cpp-tests - - wheel-build-libcuopt - - wheel-build-libcuopt-client - - wheel-build-libcuopt-mathopt - - wheel-build-libcuopt-routing - - wheel-build-cuopt - - wheel-tests-cuopt - - wheel-build-cuopt-server - - wheel-tests-cuopt-server - - wheel-build-cuopt-sh-client - - test-self-hosted-server permissions: contents: read uses: rapidsai/shared-workflows/.github/workflows/pr-builder.yaml@main @@ -73,7 +54,6 @@ jobs: echo "cuopt_server_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER|split(\".\")|map(tonumber)|.[0]) | map(max_by([(.PY_VER|split(\".\")|map(tonumber)), (.CUDA_VER|split(\".\")|map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_server_test_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER | split(\".\") | map(tonumber) | .[0]) | map(max_by([(.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_sh_client_filter=[map(select(.ARCH == \"amd64\")) | min_by((.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(-tonumber)))]" >> $GITHUB_OUTPUT - changed-files: permissions: actions: read @@ -464,411 +444,3 @@ jobs: script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} - multi-gpu-cpp-tests: - needs: [conda-cpp-build, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - uses: ./.github/workflows/multi_gpu_cpp_test.yaml - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp - with: - build_type: pull-request - secrets: inherit # zizmor: ignore[secrets-inherit] - conda-python-build: - needs: [build-details, conda-cpp-build, changed-files] - # Consumed by conda-python-tests and docs-build. - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda || - fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/conda-python-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_python.sh - # Build a conda package for each CUDA x ARCH x minimum supported Python version - matrix_filter: group_by({CUDA_VER, ARCH}) | map(min_by(.PY_VER | split(".") | map(tonumber))) - conda-python-tests: - needs: [conda-python-build, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - uses: rapidsai/shared-workflows/.github/workflows/conda-python-tests.yaml@main - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda - with: - build_type: pull-request - run_codecov: false - script: ci/test_python.sh - docs-build-matrix: - permissions: - contents: read - uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main - with: - build_type: pull-request - matrix_name: docs-build - docs-build: - needs: [docs-build-matrix, conda-python-build, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.docs-build-matrix.outputs.matrix) }} - if: fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs - with: - build_type: pull-request - node_type: "gpu-${{ matrix.GPU }}-${{ matrix.DRIVER }}-1" - arch: "${{ matrix.ARCH }}" - file_to_upload: "docs/cuopt/build/html/" - artifact-name: "cuopt_docs" - container_image: "rapidsai/ci-conda:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" - script: "ci/build_docs.sh" - # Compiles libcuopt from source (one self-contained classifier JAR per CUDA major and - # architecture), so this does not need conda-cpp-build. See #1817. - java-static-build-matrix: - needs: changed-files - permissions: - contents: read - uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || - fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp - with: - build_type: pull-request - matrix_name: conda-cpp-build - matrix_filter: 'map(. + {CUDA_MAJOR: (.CUDA_VER | split(".") | .[0])}) | unique_by([.ARCH, .CUDA_MAJOR])' - - java-static-build: - needs: [java-static-build-matrix, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || - fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp - with: - build_type: pull-request - node_type: "cpu16" - arch: ${{ matrix.ARCH }} - # ci-wheel (Rocky 8) rather than ci-conda: gcc-toolset-14 on Rocky 8 produces a libstdc++ - # ABI requirement the RAPIDS-supported platforms can actually satisfy, unlike ci-conda's - # gcc_linux-64 conda package -- the same fix cuDF applied in rapidsai/cudf#23766 after - # hitting this in production (rapidsai/cudf#23753). See setup_java_static_env.sh. - # - # Must be CUDA-version-pinned, not the bare "26.10-latest" tag: custom-job.yaml has no - # per-matrix env passthrough, so an untagged image would leave RAPIDS_CUDA_VERSION at - # that image's single baked-in default for every matrix entry. - # ci/build_java_static.sh reads it to pick the CUDA toolkit, so every "cuN" classifier - # JAR would actually be built against the same CUDA version and just mislabeled. Matches - # the pattern java-static-test (test.yaml) already uses for this image family. - container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" - script: "ci/build_java_static.sh" - artifact-name: "cuopt_java_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" - file_to_upload: "java/cuopt/classifier-jars/" - - # Runs the full Java suite against each classifier JAR on a GPU, with no libcuopt installed, - # so a JAR that loads but computes wrong answers fails here rather than at a user. - java-static-test: - needs: [java-static-build, java-static-build-matrix] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} - with: - build_type: pull-request - node_type: "gpu-l4-latest-1" - arch: ${{ matrix.ARCH }} - # A plain CUDA-devel + dnf environment rather than rapidsai/ci-conda: the packaged JAR - # only needs a JDK, Maven and the CUDA runtime (libcublas/libcusparse, already in this - # image) to test, and a fresh `conda create` every run was slow enough that concurrent - # matrix jobs' cold Maven Central resolution reliably lined up and triggered 429s. - container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" - script: "ci/test_java_static.sh" - # Surefire fork-crash diagnostics (dumpstream/hs_err files) are also printed inline by - # the script on failure, but keep the raw reports downloadable too -- the JVM sometimes - # crashes without a clean dumpstream, and per-matrix-entry artifacts survive independently - # of how much of the console log GitHub keeps. - artifact-name: "cuopt_java_static_test_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" - file_to_upload: "java/cuopt/target/surefire-reports/" - - java-build: - needs: [conda-cpp-build, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main - if: >- - fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || - fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp - with: - build_type: pull-request - node_type: "gpu-l4-latest-1" - arch: "amd64" - container_image: "rapidsai/ci-conda:26.12-latest" - script: "ci/test_java.sh" - artifact-name: "cuopt-java" - file_to_upload: "java/cuopt/target/" - wheel-build-libcuopt-client: - needs: [build-details, compute-matrix-filters, changed-files] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_client_filter }} - package-type: cpp - package-name: libcuopt_client - # The wheel name carries no CUDA suffix, so neither should the artifact. - append-cuda-suffix: false - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt_client.sh - wheel-build-libcuopt-mathopt: - needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - # Same filter as libcuopt: every arch and CUDA version, latest Python only. - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} - package-type: cpp - package-name: libcuopt_mathopt - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt_mathopt.sh - wheel-build-libcuopt-routing: - needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - # Same filter as libcuopt: every arch and CUDA version, latest Python only. - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} - package-type: cpp - package-name: libcuopt_routing - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt_routing.sh - wheel-build-libcuopt: - needs: - - build-details - - compute-matrix-filters - - changed-files - - wheel-build-libcuopt-client - - wheel-build-libcuopt-mathopt - - wheel-build-libcuopt-routing - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - # build for every combination of arch and CUDA version, but only for the latest Python - matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} - package-type: cpp - package-name: libcuopt - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_libcuopt.sh - wheel-build-cuopt: - needs: - - build-details - - wheel-build-libcuopt - - wheel-build-libcuopt-client - - wheel-build-libcuopt-mathopt - - wheel-build-libcuopt-routing - - compute-matrix-filters - - changed-files - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_cuopt.sh - package-name: cuopt - package-type: python - # Build a wheel for each CUDA x ARCH x minimum supported Python version - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_filter }} - wheel-tests-cuopt: - needs: [wheel-build-cuopt, wheel-build-cuopt-sh-client, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - with: - build_type: pull-request - script: ci/test_wheel_cuopt.sh - secrets: - script-env-secret-1-key: CUOPT_S3_URI - script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} - script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID - script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} - script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY - script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} - wheel-build-cuopt-server: - needs: [build-details, checks, compute-matrix-filters, changed-files] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_cuopt_server.sh - package-name: cuopt_server - package-type: python - pure-wheel: true - # Only need 1 package per CUDA major version. This selects "ARCH=amd64 + the latest supported Python, 1 job per major CUDA version". - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_filter }} - wheel-build-cuopt-sh-client: - needs: [build-details, compute-matrix-filters, changed-files] - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main - with: - build_type: pull-request - build-datetime: ${{ needs.build-details.outputs.build-datetime }} - script: ci/build_wheel_cuopt_sh_client.sh - package-name: cuopt_sh_client - package-type: python - append-cuda-suffix: false - pure-wheel: true - # only need 1 build (noarch package): this selects amd64, oldest-supported Python, latest-supported CUDA - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_sh_client_filter }} - wheel-tests-cuopt-server: - needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files, compute-matrix-filters] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - with: - build_type: pull-request - script: ci/test_wheel_cuopt_server.sh - matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_test_filter }} - secrets: - script-env-secret-1-key: CUOPT_S3_URI - script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} - script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID - script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} - script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY - script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} - test-self-hosted-server: - needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files] - permissions: - actions: read - contents: read - id-token: write - packages: read - pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] - uses: ./.github/workflows/self_hosted_service_test.yaml - if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels - with: - build_type: pull-request - script: ci/test_self_hosted_service.sh - pr-test-summary: - name: "PR test summary (non-blocking)" - needs: - - conda-cpp-tests-mathopt - - conda-cpp-tests-routing - - conda-python-tests - - wheel-tests-cuopt - - wheel-tests-cuopt-server - - test-self-hosted-server - if: always() - runs-on: ubuntu-latest - permissions: - actions: read - pull-requests: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - sparse-checkout: ci/utils/pr_test_summary.py - sparse-checkout-cone-mode: false - - run: python3 ci/utils/pr_test_summary.py - env: - GH_TOKEN: ${{ github.token }} From fa9f86be986a202f234c141e2c139c5f9c9e0420 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Fri, 30 Oct 2026 22:31:34 -0500 Subject: [PATCH 09/10] ci: restore full pr.yaml with the routing and mathopt cpp test jobs Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/pr.yaml | 428 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 60068c83ea..19f4f11de3 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -24,6 +24,25 @@ jobs: - conda-cpp-build - conda-cpp-tests-mathopt - conda-cpp-tests-routing + - java-build + - java-static-build-matrix + - java-static-build + - java-static-test + - conda-python-build + - conda-python-tests + - docs-build + - docs-build-matrix + - multi-gpu-cpp-tests + - wheel-build-libcuopt + - wheel-build-libcuopt-client + - wheel-build-libcuopt-mathopt + - wheel-build-libcuopt-routing + - wheel-build-cuopt + - wheel-tests-cuopt + - wheel-build-cuopt-server + - wheel-tests-cuopt-server + - wheel-build-cuopt-sh-client + - test-self-hosted-server permissions: contents: read uses: rapidsai/shared-workflows/.github/workflows/pr-builder.yaml@main @@ -54,6 +73,7 @@ jobs: echo "cuopt_server_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER|split(\".\")|map(tonumber)|.[0]) | map(max_by([(.PY_VER|split(\".\")|map(tonumber)), (.CUDA_VER|split(\".\")|map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_server_test_filter=map(select(.ARCH == \"amd64\")) | group_by(.CUDA_VER | split(\".\") | map(tonumber) | .[0]) | map(max_by([(.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(tonumber))]))" >> $GITHUB_OUTPUT echo "cuopt_sh_client_filter=[map(select(.ARCH == \"amd64\")) | min_by((.PY_VER | split(\".\") | map(tonumber)), (.CUDA_VER | split(\".\") | map(-tonumber)))]" >> $GITHUB_OUTPUT + changed-files: permissions: actions: read @@ -444,3 +464,411 @@ jobs: script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} + multi-gpu-cpp-tests: + needs: [conda-cpp-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: ./.github/workflows/multi_gpu_cpp_test.yaml + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + secrets: inherit # zizmor: ignore[secrets-inherit] + conda-python-build: + needs: [build-details, conda-cpp-build, changed-files] + # Consumed by conda-python-tests and docs-build. + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda || + fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/conda-python-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_python.sh + # Build a conda package for each CUDA x ARCH x minimum supported Python version + matrix_filter: group_by({CUDA_VER, ARCH}) | map(min_by(.PY_VER | split(".") | map(tonumber))) + conda-python-tests: + needs: [conda-python-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: rapidsai/shared-workflows/.github/workflows/conda-python-tests.yaml@main + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_conda + with: + build_type: pull-request + run_codecov: false + script: ci/test_python.sh + docs-build-matrix: + permissions: + contents: read + uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main + with: + build_type: pull-request + matrix_name: docs-build + docs-build: + needs: [docs-build-matrix, conda-python-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.docs-build-matrix.outputs.matrix) }} + if: fromJSON(needs.changed-files.outputs.changed_file_groups).build_docs + with: + build_type: pull-request + node_type: "gpu-${{ matrix.GPU }}-${{ matrix.DRIVER }}-1" + arch: "${{ matrix.ARCH }}" + file_to_upload: "docs/cuopt/build/html/" + artifact-name: "cuopt_docs" + container_image: "rapidsai/ci-conda:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" + script: "ci/build_docs.sh" + # Compiles libcuopt from source (one self-contained classifier JAR per CUDA major and + # architecture), so this does not need conda-cpp-build. See #1817. + java-static-build-matrix: + needs: changed-files + permissions: + contents: read + uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@main + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || + fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + matrix_name: conda-cpp-build + matrix_filter: 'map(. + {CUDA_MAJOR: (.CUDA_VER | split(".") | .[0])}) | unique_by([.ARCH, .CUDA_MAJOR])' + + java-static-build: + needs: [java-static-build-matrix, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || + fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + node_type: "cpu16" + arch: ${{ matrix.ARCH }} + # ci-wheel (Rocky 8) rather than ci-conda: gcc-toolset-14 on Rocky 8 produces a libstdc++ + # ABI requirement the RAPIDS-supported platforms can actually satisfy, unlike ci-conda's + # gcc_linux-64 conda package -- the same fix cuDF applied in rapidsai/cudf#23766 after + # hitting this in production (rapidsai/cudf#23753). See setup_java_static_env.sh. + # + # Must be CUDA-version-pinned, not the bare "26.10-latest" tag: custom-job.yaml has no + # per-matrix env passthrough, so an untagged image would leave RAPIDS_CUDA_VERSION at + # that image's single baked-in default for every matrix entry. + # ci/build_java_static.sh reads it to pick the CUDA toolkit, so every "cuN" classifier + # JAR would actually be built against the same CUDA version and just mislabeled. Matches + # the pattern java-static-test (test.yaml) already uses for this image family. + container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" + script: "ci/build_java_static.sh" + artifact-name: "cuopt_java_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" + file_to_upload: "java/cuopt/classifier-jars/" + + # Runs the full Java suite against each classifier JAR on a GPU, with no libcuopt installed, + # so a JAR that loads but computes wrong answers fails here rather than at a user. + java-static-test: + needs: [java-static-build, java-static-build-matrix] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.java-static-build-matrix.outputs.matrix) }} + with: + build_type: pull-request + node_type: "gpu-l4-latest-1" + arch: ${{ matrix.ARCH }} + # A plain CUDA-devel + dnf environment rather than rapidsai/ci-conda: the packaged JAR + # only needs a JDK, Maven and the CUDA runtime (libcublas/libcusparse, already in this + # image) to test, and a fresh `conda create` every run was slow enough that concurrent + # matrix jobs' cold Maven Central resolution reliably lined up and triggered 429s. + container_image: "rapidsai/ci-wheel:26.12-cuda${{ matrix.CUDA_VER }}-${{ matrix.LINUX_VER }}-py${{ matrix.PY_VER }}" + script: "ci/test_java_static.sh" + # Surefire fork-crash diagnostics (dumpstream/hs_err files) are also printed inline by + # the script on failure, but keep the raw reports downloadable too -- the JVM sometimes + # crashes without a clean dumpstream, and per-matrix-entry artifacts survive independently + # of how much of the console log GitHub keeps. + artifact-name: "cuopt_java_static_test_${{ matrix.ARCH }}_cu${{ matrix.CUDA_MAJOR }}" + file_to_upload: "java/cuopt/target/surefire-reports/" + + java-build: + needs: [conda-cpp-build, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + if: >- + fromJSON(needs.changed-files.outputs.changed_file_groups).test_java || + fromJSON(needs.changed-files.outputs.changed_file_groups).test_cpp + with: + build_type: pull-request + node_type: "gpu-l4-latest-1" + arch: "amd64" + container_image: "rapidsai/ci-conda:26.12-latest" + script: "ci/test_java.sh" + artifact-name: "cuopt-java" + file_to_upload: "java/cuopt/target/" + wheel-build-libcuopt-client: + needs: [build-details, compute-matrix-filters, changed-files] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_client_filter }} + package-type: cpp + package-name: libcuopt_client + # The wheel name carries no CUDA suffix, so neither should the artifact. + append-cuda-suffix: false + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt_client.sh + wheel-build-libcuopt-mathopt: + needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + # Same filter as libcuopt: every arch and CUDA version, latest Python only. + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} + package-type: cpp + package-name: libcuopt_mathopt + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt_mathopt.sh + wheel-build-libcuopt-routing: + needs: [build-details, compute-matrix-filters, changed-files, wheel-build-libcuopt-client] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + # Same filter as libcuopt: every arch and CUDA version, latest Python only. + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} + package-type: cpp + package-name: libcuopt_routing + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt_routing.sh + wheel-build-libcuopt: + needs: + - build-details + - compute-matrix-filters + - changed-files + - wheel-build-libcuopt-client + - wheel-build-libcuopt-mathopt + - wheel-build-libcuopt-routing + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + # build for every combination of arch and CUDA version, but only for the latest Python + matrix_filter: ${{ needs.compute-matrix-filters.outputs.libcuopt_filter }} + package-type: cpp + package-name: libcuopt + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_libcuopt.sh + wheel-build-cuopt: + needs: + - build-details + - wheel-build-libcuopt + - wheel-build-libcuopt-client + - wheel-build-libcuopt-mathopt + - wheel-build-libcuopt-routing + - compute-matrix-filters + - changed-files + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_cuopt.sh + package-name: cuopt + package-type: python + # Build a wheel for each CUDA x ARCH x minimum supported Python version + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_filter }} + wheel-tests-cuopt: + needs: [wheel-build-cuopt, wheel-build-cuopt-sh-client, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + with: + build_type: pull-request + script: ci/test_wheel_cuopt.sh + secrets: + script-env-secret-1-key: CUOPT_S3_URI + script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} + script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID + script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} + script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY + script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} + wheel-build-cuopt-server: + needs: [build-details, checks, compute-matrix-filters, changed-files] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_cuopt_server.sh + package-name: cuopt_server + package-type: python + pure-wheel: true + # Only need 1 package per CUDA major version. This selects "ARCH=amd64 + the latest supported Python, 1 job per major CUDA version". + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_filter }} + wheel-build-cuopt-sh-client: + needs: [build-details, compute-matrix-filters, changed-files] + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/wheels-build.yaml@main + with: + build_type: pull-request + build-datetime: ${{ needs.build-details.outputs.build-datetime }} + script: ci/build_wheel_cuopt_sh_client.sh + package-name: cuopt_sh_client + package-type: python + append-cuda-suffix: false + pure-wheel: true + # only need 1 build (noarch package): this selects amd64, oldest-supported Python, latest-supported CUDA + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_sh_client_filter }} + wheel-tests-cuopt-server: + needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files, compute-matrix-filters] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + uses: rapidsai/shared-workflows/.github/workflows/wheels-test.yaml@main + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + with: + build_type: pull-request + script: ci/test_wheel_cuopt_server.sh + matrix_filter: ${{ needs.compute-matrix-filters.outputs.cuopt_server_test_filter }} + secrets: + script-env-secret-1-key: CUOPT_S3_URI + script-env-secret-1-value: ${{ secrets.CUOPT_S3_URI }} + script-env-secret-2-key: CUOPT_AWS_ACCESS_KEY_ID + script-env-secret-2-value: ${{ secrets.CUOPT_AWS_ACCESS_KEY_ID }} + script-env-secret-3-key: CUOPT_AWS_SECRET_ACCESS_KEY + script-env-secret-3-value: ${{ secrets.CUOPT_AWS_SECRET_ACCESS_KEY }} + test-self-hosted-server: + needs: [wheel-build-cuopt, wheel-build-cuopt-server, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: ./.github/workflows/self_hosted_service_test.yaml + if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels + with: + build_type: pull-request + script: ci/test_self_hosted_service.sh + pr-test-summary: + name: "PR test summary (non-blocking)" + needs: + - conda-cpp-tests-mathopt + - conda-cpp-tests-routing + - conda-python-tests + - wheel-tests-cuopt + - wheel-tests-cuopt-server + - test-self-hosted-server + if: always() + runs-on: ubuntu-latest + permissions: + actions: read + pull-requests: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: ci/utils/pr_test_summary.py + sparse-checkout-cone-mode: false + - run: python3 ci/utils/pr_test_summary.py + env: + GH_TOKEN: ${{ github.token }} From 5722b9a4a20103894d0e1551554debf6c0147beb Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 2 Nov 2026 10:53:28 -0600 Subject: [PATCH 10/10] ci: install routing label markers for the gRPC routing mapper tests Co-Authored-By: Claude Sonnet 5.5 --- cpp/tests/CMakeLists.txt | 26 +++++++++++++++++--------- cpp/tests/routing/grpc/CMakeLists.txt | 2 ++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 0383138593..e3d4b68095 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -71,6 +71,22 @@ endif() set(CUOPT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +# ################################################################ ------------------------------------------------------------------ +# install_test_labels(TEST_NAME label1 [label2 ...]) +# +# Installs a .labels marker next to the test binary so ci/run_ctests.sh can select +# tests by label. Use it for tests whose LABELS are set outside ConfigureTest. +function(install_test_labels TEST_NAME) + string(REPLACE ";" "\n" _labels_text "${ARGN}") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.labels" "${_labels_text}\n") + install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.labels" + COMPONENT testing + DESTINATION bin/gtests/libcuopt + EXCLUDE_FROM_ALL + ) +endfunction() + # ################################################################ ------------------------------------------------------------------ # ConfigureTest(NAME source1.cu source2.cu [STATIC_LIB] [LABELS label1 label2 ...]) # @@ -126,15 +142,7 @@ function(ConfigureTest CMAKE_TEST_NAME) rapids_test_add(NAME ${CMAKE_TEST_NAME} COMMAND ${CMAKE_TEST_NAME} INSTALL_COMPONENT_SET testing) if(CT_LABELS) set_tests_properties(${CMAKE_TEST_NAME} PROPERTIES LABELS "${CT_LABELS}") - # Installed next to the binary so ci/run_ctests.sh can select tests by label. - string(REPLACE ";" "\n" CT_LABELS_TEXT "${CT_LABELS}") - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_TEST_NAME}.labels" "${CT_LABELS_TEXT}\n") - install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_TEST_NAME}.labels" - COMPONENT testing - DESTINATION bin/gtests/libcuopt - EXCLUDE_FROM_ALL - ) + install_test_labels(${CMAKE_TEST_NAME} ${CT_LABELS}) endif() install( TARGETS ${CMAKE_TEST_NAME} diff --git a/cpp/tests/routing/grpc/CMakeLists.txt b/cpp/tests/routing/grpc/CMakeLists.txt index 98e0bd9500..764e9de051 100644 --- a/cpp/tests/routing/grpc/CMakeLists.txt +++ b/cpp/tests/routing/grpc/CMakeLists.txt @@ -67,6 +67,7 @@ endif() rapids_test_add(NAME GRPC_ROUTING_PROBLEM_MAPPER_TEST COMMAND GRPC_ROUTING_PROBLEM_MAPPER_TEST INSTALL_COMPONENT_SET testing) set_tests_properties(GRPC_ROUTING_PROBLEM_MAPPER_TEST PROPERTIES LABELS "routing") +install_test_labels(GRPC_ROUTING_PROBLEM_MAPPER_TEST routing) # Settings mapper round-trip (no running server). This mapper reads # routing::solver_settings_t, so it covers the host-only accessors that build into @@ -100,6 +101,7 @@ endif() rapids_test_add(NAME GRPC_ROUTING_SETTINGS_MAPPER_TEST COMMAND GRPC_ROUTING_SETTINGS_MAPPER_TEST INSTALL_COMPONENT_SET testing) set_tests_properties(GRPC_ROUTING_SETTINGS_MAPPER_TEST PROPERTIES LABELS "routing") +install_test_labels(GRPC_ROUTING_SETTINGS_MAPPER_TEST routing) install( TARGETS GRPC_ROUTING_SETTINGS_MAPPER_TEST