Skip to content

test(conda): guard the per-component package boundaries - #1938

Closed
ramakrishnap-nv wants to merge 1 commit into
feat/split-conda-packagesfrom
test/conda-component-guards
Closed

ramakrishnap-nv wants to merge 1 commit into
feat/split-conda-packagesfrom
test/conda-component-guards

Conversation

@ramakrishnap-nv

@ramakrishnap-nv ramakrishnap-nv commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #1928.

#1928 already loads each component library with RTLD_NOW in an environment holding only that package and its declared dependencies. Four gaps remain:

Output Gap Added
libcuopt-mathopt cuopt_cli only checked for existence run cuopt_cli --help
libcuopt-routing "no longer pulls cusparse, cudss or nccl" is unasserted assert absent from the solved env
libcuopt-client "no CUDA math libs" is unasserted assert cublas/cusparse/cudss/nccl absent
libcuopt libcuopt.so is an ld script, so CDLL cannot cover it parse INPUT(), load each library
libcuopt cuopt-config.cmake unguarded add it and cuopt-targets.cmake to package_contents
libcuopt-tests no tests: block package_contents for three test binaries

The load tests pass whether or not the heavy CUDA libraries are present, so they cannot catch the split regressing. The new assertions run against the solved environment, so a transitive run_export is caught too. rattler-build gives each tests: entry its own environment, so this needs no extra CI job.

Verification

Recipe renders all six outputs under rattler-build 0.57.2 (CI's version). The ld-script parser and conda-meta lookup were run against an installed tree: the parser returns the three components and all three CDLL-load; the lookup detects libcusparse, libcudss, nccl, libcublas and librmm when present, so the assertions fail rather than pass vacuously. cuopt_cli --help exits 0 with no GPU.

Not verified: the tests have not run in the real per-output environments, which needs a full conda C++ build.

Checklist

  • I am familiar with the Contributing Guidelines.
  • Testing
    • New or existing tests cover these changes
  • Documentation
    • NA

🤖 Generated with Claude Code

@copy-pr-bot

copy-pr-bot Bot commented Sep 18, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@ramakrishnap-nv ramakrishnap-nv self-assigned this Sep 18, 2026
@ramakrishnap-nv ramakrishnap-nv added non-breaking Introduces a non-breaking change improvement Improves an existing functionality labels Sep 18, 2026
@ramakrishnap-nv ramakrishnap-nv added this to the 26.10 milestone Sep 18, 2026
The component outputs already load their own library with RTLD_NOW. Four gaps remain:

- cuopt_cli is only checked for existence; the executable has its own DT_NEEDED
  closure that loading libcuopt_mathopt.so does not exercise, so run it.
- "A routing-only install no longer pulls cusparse, cudss or nccl" is unasserted:
  the load test passes either way. Assert absence from the solved environment, so
  a transitive run_export that re-adds one is caught. Same for the CUDA math
  libraries in libcuopt-client.
- libcuopt.so is a GNU ld script, not an ELF object, so CDLL cannot load it. Parse
  its INPUT() list and load every library it names. Its package_contents also now
  covers cuopt-config.cmake and cuopt-targets.cmake, which find_package(cuopt)
  needs and which are easy to drop when moving installs between outputs.
- libcuopt-tests had no tests block; ci/run_ctests.sh globs
  bin/gtests/libcuopt/*_TEST, so an install landing them elsewhere leaves CI
  running zero tests and still passing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@ramakrishnap-nv
ramakrishnap-nv force-pushed the test/conda-component-guards branch from df5c9bf to 270437a Compare September 18, 2026 20:02
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ramakrishnap-nv
ramakrishnap-nv marked this pull request as ready for review September 18, 2026 20:07
@ramakrishnap-nv
ramakrishnap-nv requested a review from a team as a code owner September 18, 2026 20:07
@ramakrishnap-nv
ramakrishnap-nv requested review from bdice and removed request for a team September 18, 2026 20:07
@ramakrishnap-nv
ramakrishnap-nv marked this pull request as draft September 18, 2026 20:08
@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 27ba34b9-b719-4f42-985f-eb57aa154414

📥 Commits

Reviewing files that changed from the base of the PR and between e4166af and 270437a.

📒 Files selected for processing (1)
  • conda/recipes/libcuopt/recipe.yaml

Included review availability: Your plan provides up to 12 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The conda recipe adds tests for libcuopt dependency isolation, executable startup, package contents, linker-script component loading, CMake files, and installed integration test executables.

Changes

libcuopt package validation

Layer / File(s) Summary
Dependency isolation tests
conda/recipes/libcuopt/recipe.yaml
Solved-environment tests reject forbidden CUDA libraries for libcuopt-client and libcuopt-routing.
Mathopt executable smoke test
conda/recipes/libcuopt/recipe.yaml
The libcuopt-mathopt package runs cuopt_cli --help.
Package contents and library loadability
conda/recipes/libcuopt/recipe.yaml
libcuopt checks its CMake files, parses its linker script, loads component libraries with immediate symbol resolution, and verifies installed integration test executables.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Other

Suggested reviewers: bdice

Merge Risk: ⚪ Minimal · up to 27043

The added checks target the intended package artifacts without an identified false failure or packaging regression. The change is ready to merge after normal validation.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the conda test changes that enforce package boundaries between components.
Description check ✅ Passed The description directly explains the added package-boundary tests, their coverage, and verification status.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator Author

Closing — the maintenance cost outweighs the value in this shape.

Keeping the context here for whoever picks this up.

What prompted it. The component packages in #1928 as actually built pull the libraries the split is meant to remove. Solving a routing-only environment from the CI artifact gives libcublas, libcudss, libcusparse and nccl — 834 MB. The client-only environment pulls the same four.

Root cause. Every output inherits run_exports from the shared top-level cache: host environment, not just from its own host:. The per-output ignore_run_exports lists only suppress the output's own. Verified with a minimal recipe under rattler-build 0.57.2: an output declaring no requirements at all still inherits the cache's exports.

That is also why CI went red, though only by luck — one of the ~18 leaked exports was cuda-version, pinned to the build's CUDA minor, which broke the test-environment solve. The libcusparse / libcudss / nccl leak on its own resolves fine and would have shipped silently.

Why not this PR. The routing and client checks were denylists of forbidden package names. They fail correctly today, but they decay silently: a heavy dependency added later that isn't on the list is simply not covered, and nothing ever goes red to say so.

Better fix. ignore_run_exports on the cache: block. Verified that it suppresses only the cache's exports — an output declaring a package in its own host: still gets the correct ABI-tight pin. That closes the invisible channel, so a component can only gain a dependency via a line someone wrote in the recipe, which review catches. Weaker than an assertion, but no list to maintain.

Worth revisiting are the two items here with nothing to maintain: cuopt_cli --help (the executable has its own DT_NEEDED closure that loading the .so does not exercise) and cuopt-config.cmake / cuopt-targets.cmake in package_contents (5112f48 exists because those files were dropped once already).

@github-actions

Copy link
Copy Markdown

CI Test Summary

✅ All 14 test job(s) passed. (2 skipped)

@ramakrishnap-nv
ramakrishnap-nv deleted the test/conda-component-guards branch October 16, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant