Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6900497
java: add cuopt-java skeleton with FFM bridge demo
rgsl888prabhu May 8, 2026
81ed6f3
java/ci: add CI workflows and complete dependencies.yaml integration
rgsl888prabhu May 8, 2026
8f7770d
java: add LP/MILP/QP public API and FFM implementation
rgsl888prabhu May 11, 2026
92daba7
java: auto-download jextract on first build (cuvs pattern)
rgsl888prabhu May 11, 2026
5b75bd2
java: fix MR-JAR test path, libcuopt lookup, and commit panama bindings
rgsl888prabhu May 11, 2026
904d855
fix generation
rgsl888prabhu May 11, 2026
1ac4434
java: add arm64 build support
rgsl888prabhu May 12, 2026
d73133e
java/ci: run arm64 integration tests on GPU runner
rgsl888prabhu May 12, 2026
ed165e2
java: bundle libcuopt + RAPIDS deps in per-(arch,cuda) classifier JARs
rgsl888prabhu May 12, 2026
a9cf642
java: wrap MIP user callbacks (cuOptSetMIP{Get,Set}SolutionCallback)
rgsl888prabhu May 12, 2026
6283b6f
[TEMP] ci: disable non-Java PR lanes while iterating on cuopt-java
rgsl888prabhu May 12, 2026
eb91e7e
ci: list all jobs in pr-builder.needs (fix rapids-check-pr-job-depend…
rgsl888prabhu May 12, 2026
6d8fe2d
Revert "ci: list all jobs in pr-builder.needs" and "[TEMP] ci: disabl…
rgsl888prabhu May 12, 2026
2e3d2fe
ci: list java build-and-tests matrix jobs in pr-builder.needs
rgsl888prabhu May 12, 2026
e5cbab8
java/ci: pass major.minor CUDA version to dep-file-generator
rgsl888prabhu May 12, 2026
aee7ed4
Merge branch 'main' into feat/java-api-skeleton
rgsl888prabhu May 12, 2026
182d518
[TEMP] ci: prune non-Java PR lanes while iterating on cuopt-java
rgsl888prabhu May 12, 2026
0aff867
ci: silence zizmor secrets-inherit on Java jobs
rgsl888prabhu May 12, 2026
8259ac5
ci: add per-job permissions blocks to the Java jobs
rgsl888prabhu May 12, 2026
9689442
ci: silence zizmor secrets-inherit on Java build.yaml jobs
rgsl888prabhu May 12, 2026
54a8b9c
java/ci: skip panama bindings regen in CI
rgsl888prabhu May 12, 2026
f27ed56
ci/java: add CUDA runtime libs to test_java conda env
rgsl888prabhu May 13, 2026
03ea02e
ci/java: fix CUDA runtime package name (libcudart → cuda-cudart)
rgsl888prabhu May 13, 2026
c609cb8
java: consistent naming for acronyms (MIP/QP/CSR/IP)
rgsl888prabhu May 13, 2026
de14d0e
java: shrink API surface per review (drop ranged constraints + DataMo…
rgsl888prabhu May 13, 2026
cd20d99
java: lowercase brand prefix on cuOpt-named classes
rgsl888prabhu May 13, 2026
4925008
java: rename linear_programming package → optimization (+ MIPCallbackIT)
rgsl888prabhu May 14, 2026
49f2ab9
java/ci: always build the classifier JAR in CI
rgsl888prabhu May 14, 2026
cca5db7
java/ci: include libcuopt + libmps_parser in classifier JAR
rgsl888prabhu May 14, 2026
7581840
Merge remote-tracking branch 'origin/main' into feat/java-api-skeleton
rgsl888prabhu May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,42 @@ jobs:
artifact-name: "cuopt_docs"
container_image: "rapidsai/ci-conda:26.06-latest"
script: "ci/build_docs.sh"
java-build:
# Build cuopt-java JAR (amd64) for main / release-branch / tag pushes.
# Integration tests are not run here — they live in test.yaml.
needs: [cpp-build]
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main
with:
build_type: ${{ inputs.build_type || 'branch' }}
node_type: "linux-amd64-cpu16"
sha: ${{ inputs.sha }}
branch: ${{ inputs.branch }}
date: ${{ inputs.date }}
arch: "amd64"
file_to_upload: "java/cuopt-java/target/"
artifact-name: "cuopt-java"
container_image: "rapidsai/ci-conda:26.06-latest"
script: "ci/build_java.sh"
java-build-arm64:
# Build cuopt-java JAR (arm64) for main / release-branch / tag pushes.
# Build-only (no IT) — matches the amd64 java-build sibling. PR
# integration tests run on the conda-java-build-and-tests-arm64
# GPU job in pr.yaml.
needs: [cpp-build]
secrets: inherit # zizmor: ignore[secrets-inherit]
uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main
with:
build_type: ${{ inputs.build_type || 'branch' }}
node_type: "linux-arm64-cpu16"
sha: ${{ inputs.sha }}
branch: ${{ inputs.branch }}
date: ${{ inputs.date }}
arch: "arm64"
file_to_upload: "java/cuopt-java/target/"
artifact-name: "cuopt-java-arm64"
container_image: "rapidsai/ci-conda:26.06-latest"
script: "ci/build_java.sh"
wheel-build-cuopt-sh-client:
permissions:
actions: read
Expand Down
80 changes: 80 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ jobs:
- checks
- conda-cpp-build
- conda-cpp-tests
- conda-java-build-and-tests-matrix
- conda-java-build-and-tests
- conda-java-build-and-tests-arm64-matrix
- conda-java-build-and-tests-arm64
- conda-python-build
- conda-python-tests
- docs-build
Expand Down Expand Up @@ -418,6 +422,82 @@ 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 }}
conda-java-build-and-tests-matrix:
# Derives the matrix from conda-cpp-build, filtered to amd64. The arm64
# sibling job conda-java-build-and-tests-arm64 handles arm64.
needs: [conda-cpp-build, changed-files]
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_java
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@cuda-13.2.0
with:
build_type: pull-request
matrix_name: conda-cpp-build
matrix_filter: 'map(select(.ARCH == "amd64"))'
conda-java-build-and-tests:
# Combined build+test in one job (matches cuvs pattern). Splitting
# this is a follow-up: requires shared-workflow surface for cross-job
# artifact passing. cuvs Issue #868 tracks the same split.
needs: conda-java-build-and-tests-matrix
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_java
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@cuda-13.2.0
with:
build_type: pull-request
node_type: "gpu-l4-latest-1"
arch: "amd64"
script: "ci/test_java.sh"
file_to_upload: "java/cuopt-java/target/"
artifact-name: "cuopt-java-cuda${{ needs.conda-java-build-and-tests-matrix.outputs.CUDA_VER }}"
conda-java-build-and-tests-arm64-matrix:
# Matrix for the arm64 Java build+tests, filtered to arm64 rows of
# conda-cpp-build. Sibling of conda-java-build-and-tests-matrix
# which handles amd64.
needs: [conda-cpp-build, changed-files]
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_java
permissions:
actions: read
contents: read
id-token: write
packages: read
pull-requests: read
uses: rapidsai/shared-workflows/.github/workflows/compute-matrix.yaml@cuda-13.2.0
with:
build_type: pull-request
matrix_name: conda-cpp-build
matrix_filter: 'map(select(.ARCH == "arm64"))'
conda-java-build-and-tests-arm64:
# Build the JAR + run unit + integration tests on arm64 GPU. Mirrors
# conda-java-build-and-tests (amd64). custom-job.yaml resolves
# runs-on to "linux-${arch}-${node_type}", so node_type is the
# suffix only (same as the amd64 sibling above).
needs: conda-java-build-and-tests-arm64-matrix
if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_java
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@cuda-13.2.0
with:
build_type: pull-request
node_type: "gpu-l4-latest-1"
arch: "arm64"
script: "ci/test_java.sh"
file_to_upload: "java/cuopt-java/target/"
artifact-name: "cuopt-java-arm64-cuda${{ needs.conda-java-build-and-tests-arm64-matrix.outputs.CUDA_VER }}"
conda-python-build:
needs: [conda-cpp-build, compute-matrix-filters, changed-files]
# Consumed by conda-python-tests and docs-build.
Expand Down
102 changes: 102 additions & 0 deletions ci/build_java.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Build cuopt-java in CI.
#
# Usage:
# ci/build_java.sh # build only, skip tests
# ci/build_java.sh --run-java-tests # build + unit + integration tests (GPU required)
# ci/build_java.sh --unit-tests-only # build + unit tests, skip IT (no GPU available)
#
# Inputs (set by RAPIDS shared workflow):
# RAPIDS_CUDA_VERSION
#
# Outputs:
# java/cuopt-java/target/cuopt-java-*.jar (uploaded by the calling
# workflow via artifact-name)

set -euo pipefail

EXITCODE=0
trap "EXITCODE=1" ERR
set +e

# Argument handling — match cuvs build_java.sh contract
RUN_JAVA_TESTS="false"
UNIT_TESTS_ONLY="false"
case "${1:-}" in
--run-java-tests) RUN_JAVA_TESTS="true" ;;
--unit-tests-only) UNIT_TESTS_ONLY="true" ;;
esac

source rapids-configure-sccache

. /opt/conda/etc/profile.d/conda.sh

rapids-logger "Configuring conda strict channel priority"
conda config --set channel_priority strict

# Pull libcuopt conda package built by upstream conda-cpp-build job.
# libcuopt.so + cuopt_c.h + constants.h end up in $CPP_CHANNEL.
CPP_CHANNEL=$(rapids-download-conda-from-github cpp)

rapids-logger "Generate Java conda environment"
rapids-dependency-file-generator \
--output conda \
--file-key test_java \
--matrix "cuda=${RAPIDS_CUDA_VERSION%.*};arch=$(arch)" \
--prepend-channel "${CPP_CHANNEL}" \
| tee env.yaml

rapids-mamba-retry env create --yes -f env.yaml -n java

set +u
conda activate java
set -u

rapids-logger "Build cuopt-java (run_tests=${RUN_JAVA_TESTS})"

# Point the Java build at the conda prefix where libcuopt lives.
export CUOPT_INCLUDE="${CONDA_PREFIX}/include"
export CMAKE_PREFIX_PATH="${CONDA_PREFIX}/lib"

# Produce the per-(arch, cuda) classifier JAR alongside the base JAR
# on every CI run. The classifier JAR bundles libcuopt.so + libmps_parser.so
# + librmm.so + librapids_logger.so and carries the manifest entry
# Embedded-Libraries-Cuda-Version. Matches cuvs's java/build.sh behavior
# of always activating the build profile (cuvs sets -P $arch-cuda$major).
export CLASSIFIER_CUDA="${RAPIDS_CUDA_VERSION%%.*}"

# In CI there is no local cpp/build directory; libcuopt.so + libmps_parser.so
# come from the conda env populated by rapids-download-conda-from-github.
# Tell the maven classifier-jar profile to pull them from $CONDA_PREFIX/lib.
export NATIVE_CPP_BUILD_PATH="${CONDA_PREFIX}/lib"

# jextract is auto-downloaded by panama-bindings/generate-bindings.sh on
# first run (cuvs pattern). No CI image change required.
#
# SKIP_DRIFT_CHECK=true in CI because the CI build uses conda's headers
# ($CONDA_PREFIX/include) while dev uses repo headers (cpp/include);
# minor formatting differences between the two sources would falsely
# trip the drift gate. The dev-workstation gate (./java/build.sh
# without this flag) is the authoritative one.
# SKIP_BINDINGS_REGEN=true because the conda env used in CI does not
# install CUDA development headers (only libcuopt + openjdk + maven),
# so jextract cannot regenerate the panama bindings from cuopt_c.h.
# The committed bindings are trusted; the dev-workstation drift gate
# in ./java/build.sh (run without SKIP_DRIFT_CHECK locally) is the
# authoritative check that they stay in sync.
if [[ "${RUN_JAVA_TESTS}" == "true" ]]; then
SKIP_DRIFT_CHECK=true SKIP_BINDINGS_REGEN=true ./java/build.sh
elif [[ "${UNIT_TESTS_ONLY}" == "true" ]]; then
SKIP_DRIFT_CHECK=true SKIP_BINDINGS_REGEN=true UNIT_TESTS_ONLY=true ./java/build.sh
else
SKIP_DRIFT_CHECK=true SKIP_BINDINGS_REGEN=true SKIP_TESTS=true ./java/build.sh
fi

rapids-logger "Show sccache stats"
sccache --show-adv-stats || true

rapids-logger "Build script exiting with value: $EXITCODE"
exit ${EXITCODE}
31 changes: 31 additions & 0 deletions ci/test_java.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Run cuopt-java tests in CI.
#
# Currently a thin wrapper that delegates to ci/build_java.sh with the
# --run-java-tests flag (matches cuvs's pattern). The build/test split
# tracked in cuvs Issue #868 is a deferred follow-up — switching to
# pre-built artifact consumption requires shared-workflow surface area
# for cross-job artifact download that doesn't exist yet.

set -euo pipefail

EXITCODE=0
trap "EXITCODE=1" ERR
set +e

rapids-logger "Check GPU usage"
nvidia-smi

rapids-logger "Run Java build and tests"

# TODO(java-build-test-split): switch to consuming a prebuilt JAR from
# conda-java-build job. Requires custom-job.yaml to expose artifact
# download or use of actions/download-artifact in this script.
# Ref: cuvs Issue rapidsai/cuvs#868
ci/build_java.sh --run-java-tests

rapids-logger "Test script exiting with value: $EXITCODE"
exit ${EXITCODE}
7 changes: 7 additions & 0 deletions conda/environments/all_cuda-129_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- clang==20.1.8
- cmake>=4.0
- cpp-argparse
- cuda-cudart
- cuda-nvcc
- cuda-nvtx-dev
- cuda-python>=12.9.2,<13.0
Expand All @@ -30,15 +31,20 @@ dependencies:
- jsonref==1.1.0
- libabseil
- libboost-devel
- libcublas
- libcudss
- libcudss-dev >=0.7
- libcurand-dev
- libcusolver-dev
- libcusparse
- libcusparse-dev
- libgrpc >=1.78.0,<1.80.0a0
- libnvjitlink
- libprotobuf
- libraft-headers==26.6.*,>=0.0.0a0
- librmm==26.6.*,>=0.0.0a0
- make
- maven>=3.9.6
- msgpack-numpy==0.4.8
- msgpack-python==1.1.2
- myst-parser
Expand All @@ -48,6 +54,7 @@ dependencies:
- numba>=0.60.0,<0.65.0
- numpy>=1.23.5,<3.0
- numpydoc
- openjdk=22.*
- openssl
- pandas>=2.0
- pexpect
Expand Down
7 changes: 7 additions & 0 deletions conda/environments/all_cuda-129_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- clang==20.1.8
- cmake>=4.0
- cpp-argparse
- cuda-cudart
- cuda-nvcc
- cuda-nvtx-dev
- cuda-python>=12.9.2,<13.0
Expand All @@ -30,15 +31,20 @@ dependencies:
- jsonref==1.1.0
- libabseil
- libboost-devel
- libcublas
- libcudss
- libcudss-dev >=0.7
- libcurand-dev
- libcusolver-dev
- libcusparse
- libcusparse-dev
- libgrpc >=1.78.0,<1.80.0a0
- libnvjitlink
- libprotobuf
- libraft-headers==26.6.*,>=0.0.0a0
- librmm==26.6.*,>=0.0.0a0
- make
- maven>=3.9.6
- msgpack-numpy==0.4.8
- msgpack-python==1.1.2
- myst-parser
Expand All @@ -48,6 +54,7 @@ dependencies:
- numba>=0.60.0,<0.65.0
- numpy>=1.23.5,<3.0
- numpydoc
- openjdk=22.*
- openssl
- pandas>=2.0
- pexpect
Expand Down
7 changes: 7 additions & 0 deletions conda/environments/all_cuda-132_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- clang==20.1.8
- cmake>=4.0
- cpp-argparse
- cuda-cudart
- cuda-nvcc
- cuda-nvtx-dev
- cuda-python>=13.0.1,<14.0
Expand All @@ -30,15 +31,20 @@ dependencies:
- jsonref==1.1.0
- libabseil
- libboost-devel
- libcublas
- libcudss
- libcudss-dev >=0.7
- libcurand-dev
- libcusolver-dev
- libcusparse
- libcusparse-dev
- libgrpc >=1.78.0,<1.80.0a0
- libnvjitlink
- libprotobuf
- libraft-headers==26.6.*,>=0.0.0a0
- librmm==26.6.*,>=0.0.0a0
- make
- maven>=3.9.6
- msgpack-numpy==0.4.8
- msgpack-python==1.1.2
- myst-parser
Expand All @@ -48,6 +54,7 @@ dependencies:
- numba>=0.60.0,<0.65.0
- numpy>=1.23.5,<3.0
- numpydoc
- openjdk=22.*
- openssl
- pandas>=2.0
- pexpect
Expand Down
Loading