Skip to content

Conversation

@ananas-block
Copy link
Contributor

@ananas-block ananas-block commented Dec 12, 2025

Summary by CodeRabbit

Release Notes

  • Refactor

    • Improved internal binary resolution logic with enhanced path handling.
  • Tests

    • Added module-level tests for binary discovery functionality.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

Walkthrough

The find_light_bin function now resolves symlinks to the light binary and traverses upward from the resolved path to locate a bin directory containing account_compression.so, improving path derivation beyond simple directory manipulation. Devenv behavior remains unchanged. Tests added for non-devenv scenarios.

Changes

Cohort / File(s) Summary
Symlink resolution and binary discovery
sdk-libs/program-test/src/utils/find_light_bin.rs
Replaces direct path manipulation with symlink resolution pipeline: reads symlink target, canonicalizes it (handling relative and absolute targets), then searches upward from resolved path for bin directory containing account_compression.so. Adds fs import and module-scoped tests for non-devenv configuration.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Pay close attention to symlink resolution edge cases (broken symlinks, relative vs. absolute targets, path canonicalization behavior across platforms)
  • Verify test coverage comprehensively exercises both successful and unsuccessful search scenarios
  • Confirm that the hierarchical search correctly terminates and doesn't have unbounded directory traversal

Poem

🔗 A symlink leads the way,
Up through directories we stray,
Finding bin where compressors play,
Paths resolved, no more delay! 📁

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions 'yarn and bun light cli support' but the changeset only modifies find_light_bin.rs to add symlink resolution and hierarchical search for account_compression.so, with no evidence of yarn/bun integration. Revise the title to accurately describe the actual changes, such as 'refactor: improve light binary path resolution with symlink handling' or clarify the PR objectives if yarn/bun support is intended but not yet implemented.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 70.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jorrit/feat-program-test-yarn-bun-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@ananas-block ananas-block force-pushed the jorrit/feat-program-test-yarn-bun-support branch from f2656af to cbe4904 Compare December 12, 2025 16:33
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2953172 and cbe4904.

⛔ Files ignored due to path filters (2)
  • .github/workflows/sdk-tests.yml is excluded by none and included by none
  • js/stateless.js/src/programs/system/layout.ts is excluded by none and included by none
📒 Files selected for processing (1)
  • sdk-libs/program-test/src/utils/find_light_bin.rs (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
sdk-libs/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Unit tests in sdk-libs must not depend on light-test-utils; integration tests must be located in sdk-tests/

Files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run Light system program compression tests using `cargo test-sbf -p system-test -- test_with_compression` and `cargo test-sbf -p system-test --test test_re_init_cpi_account` to test compressed account operations
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.803Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/Cargo.toml : Use path references in Cargo.toml dependencies pointing to `/Users/ananas/dev/light-protocol2/sdk-libs/` for light-ctoken-sdk, light-ctoken-types, light-sdk, light-sdk-types, and light-program-test
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run account-compression tests using `cargo test-sbf -p account-compression-test` to test core account compression program (Merkle tree management)
📚 Learning: 2025-12-07T03:17:28.803Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.803Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/Cargo.toml : Use path references in Cargo.toml dependencies pointing to `/Users/ananas/dev/light-protocol2/sdk-libs/` for light-ctoken-sdk, light-ctoken-types, light-sdk, light-sdk-types, and light-program-test

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-12-06T00:50:31.314Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T00:50:31.314Z
Learning: Applies to program-libs/**/*.rs : Unit tests in program-libs must not depend on light-test-utils; tests requiring light-test-utils must be located in program-tests/

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-12-06T00:50:31.314Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T00:50:31.314Z
Learning: Applies to sdk-libs/**/*.rs : Unit tests in sdk-libs must not depend on light-test-utils; integration tests must be located in sdk-tests/

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-12-06T00:50:31.314Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T00:50:31.314Z
Learning: Applies to programs/**/*.rs : Unit tests in programs must not depend on light-test-utils; integration tests must be located in program-tests/

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-12-06T00:49:57.458Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-token-test/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:57.458Z
Learning: Applies to sdk-tests/sdk-token-test/**/*test.rs : Tests should use light-ctoken-sdk functions from sdk-libs/compressed-token-sdk for testing ctoken instructions

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Depend on light-account-checks crate for account validation and discriminator checks

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-12-07T03:17:28.803Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-07T03:17:28.803Z
Learning: Applies to sdk-tests/sdk-ctoken-test/src/{lib,main}.rs : Structure Solana BPF projects with src/lib.rs containing the program entrypoint and instruction handlers

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Use light-merkle-tree-reference crate as dev dependency for reference implementation of indexed Merkle trees and generating constants

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run Light system program compression tests using `cargo test-sbf -p system-test -- test_with_compression` and `cargo test-sbf -p system-test --test test_re_init_cpi_account` to test compressed account operations

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Depend on light-compressed-account crate for compressed account types and utilities

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run E2E extended tests after building the small compressed token program using `pnpm --filter lightprotocol/programs run build-compressed-token-small` followed by `cargo test-sbf -p e2e-test -- --test test_10_all`

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run system CPI V1 tests using `cargo test-sbf -p system-cpi-test` to test Cross-Program Invocation with Light system program V1

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run account-compression tests using `cargo test-sbf -p account-compression-test` to test core account compression program (Merkle tree management)

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: All integration tests in the program-tests directory depend on `program-tests/utils` (light-test-utils) for shared test infrastructure, except `zero-copy-derive-test`

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run Light system program address tests using `cargo test-sbf -p system-test -- test_with_address` to test address-based operations

Applied to files:

  • sdk-libs/program-test/src/utils/find_light_bin.rs
🔇 Additional comments (3)
sdk-libs/program-test/src/utils/find_light_bin.rs (3)

7-8: LGTM: Imports appropriately scoped.

The addition of fs for symlink operations and scoping of process::Command within the non-devenv block is clean and correct.


67-94: LGTM: Test module appropriately validates the functionality.

The test is correctly scoped to non-devenv builds and includes helpful diagnostic output. The conditional assertions (lines 84-92) are good practice since the light CLI may not be installed in all test environments.

The test complies with the coding guideline that unit tests in sdk-libs must not depend on light-test-utils.


34-45: Traversal logic is sound, but verify across package managers.

The upward directory traversal correctly locates the bin/ directory containing account_compression.so. The validation check on line 41 ensures the right directory is found.

However, verify this works correctly across different package manager layouts (npm, yarn, pnpm, bun) as they may have different directory structures.

Run the following script to verify the package structures:

#!/bin/bash
# Description: Test find_light_bin with different package managers if available

echo "=== Testing light binary resolution ==="

# Check if light is installed
if ! command -v light &> /dev/null; then
    echo "light CLI not found - skipping verification"
    exit 0
fi

echo "Light binary location:"
which light

echo -e "\nChecking if it's a symlink:"
if [ -L "$(which light)" ]; then
    echo "Yes, symlink to:"
    readlink "$(which light)"
    echo "Resolved path:"
    readlink -f "$(which light)"
else
    echo "No, regular file"
fi

echo -e "\nSearching for account_compression.so near light binary:"
fd -t f "account_compression.so" "$(dirname $(dirname $(which light)))" 2>/dev/null | head -5

Comment on lines +21 to +32
// Follow the symlink to find the actual script location.
// This works for npm, bun, and yarn which all create symlinks from their
// bin directory to the actual script in the package.
let symlink_target = fs::read_link(&light_path).ok()?;

Some(node_modules_bin.canonicalize().unwrap_or(node_modules_bin))
// Resolve relative symlinks (e.g., "../lib/node_modules/...")
let resolved_path = if symlink_target.is_relative() {
let parent = light_path.parent()?;
parent.join(&symlink_target).canonicalize().ok()?
} else {
symlink_target.canonicalize().ok()?
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Breaks direct installations by assuming symlink.

Line 24 uses fs::read_link(&light_path).ok()? which immediately returns None if light is not a symlink. This breaks scenarios where:

  • The light binary is copied directly to a bin directory
  • It's installed without package managers (direct download/build)
  • It's a hard link rather than a symbolic link

The function should handle both symlinks and regular files.

Apply this diff to handle both cases:

-        // Follow the symlink to find the actual script location.
-        // This works for npm, bun, and yarn which all create symlinks from their
-        // bin directory to the actual script in the package.
-        let symlink_target = fs::read_link(&light_path).ok()?;
-
-        // Resolve relative symlinks (e.g., "../lib/node_modules/...")
-        let resolved_path = if symlink_target.is_relative() {
-            let parent = light_path.parent()?;
-            parent.join(&symlink_target).canonicalize().ok()?
-        } else {
-            symlink_target.canonicalize().ok()?
-        };
+        // If light is a symlink (npm, bun, yarn), follow it to the actual script.
+        // Otherwise, use the binary path directly.
+        let resolved_path = if let Ok(symlink_target) = fs::read_link(&light_path) {
+            // Resolve relative symlinks (e.g., "../lib/node_modules/...")
+            if symlink_target.is_relative() {
+                let parent = light_path.parent()?;
+                parent.join(&symlink_target).canonicalize().ok()?
+            } else {
+                symlink_target.canonicalize().ok()?
+            }
+        } else {
+            // Not a symlink, use the path directly
+            light_path.canonicalize().ok()?
+        };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Follow the symlink to find the actual script location.
// This works for npm, bun, and yarn which all create symlinks from their
// bin directory to the actual script in the package.
let symlink_target = fs::read_link(&light_path).ok()?;
Some(node_modules_bin.canonicalize().unwrap_or(node_modules_bin))
// Resolve relative symlinks (e.g., "../lib/node_modules/...")
let resolved_path = if symlink_target.is_relative() {
let parent = light_path.parent()?;
parent.join(&symlink_target).canonicalize().ok()?
} else {
symlink_target.canonicalize().ok()?
};
// If light is a symlink (npm, bun, yarn), follow it to the actual script.
// Otherwise, use the binary path directly.
let resolved_path = if let Ok(symlink_target) = fs::read_link(&light_path) {
// Resolve relative symlinks (e.g., "../lib/node_modules/...")
if symlink_target.is_relative() {
let parent = light_path.parent()?;
parent.join(&symlink_target).canonicalize().ok()?
} else {
symlink_target.canonicalize().ok()?
}
} else {
// Not a symlink, use the path directly
light_path.canonicalize().ok()?
};

@sergeytimoshin sergeytimoshin merged commit 51dfecf into main Dec 12, 2025
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants