Skip to content

feat: support binaries with arch or OS as extension#183

Merged
pirafrank merged 9 commits intomainfrom
feat/support-custom-extensions
Mar 4, 2026
Merged

feat: support binaries with arch or OS as extension#183
pirafrank merged 9 commits intomainfrom
feat/support-custom-extensions

Conversation

@pirafrank
Copy link
Owner

@pirafrank pirafrank commented Mar 3, 2026

Changed

  • fix: support additional cases, commented out unsupported OS
  • fix: improved code slightly

Description

This pull request refactors and improves the asset selection logic in src/core/selector.rs to make binary matching more robust and accurate, especially for executables that use OS or architecture labels as file extensions. It also adds new tests and test assets to verify these improvements.

Asset Selection Logic Improvements

  • Refactored the OS and architecture matching in get_triple_score to use early returns as deal-breakers if the current OS or architecture is not found in their respective hashmaps, making the logic more robust for unsupported platforms. [1] [2]
  • Enhanced filename pattern checks to better handle executables that use OS or architecture labels as extensions, awarding bonus points for matches and ensuring only meaningful binary assets are selected. The logic now prioritizes non-archived executables and explicitly supported extensions.
  • Updated the patch for assets missing OS labels, specifically for Linux, to use the new is_linux helper for clarity and correctness.
  • Commented out unused OS aliases in the OPERATING_SYSTEM map to focus matching on relevant platforms.

Test Coverage

  • Added a new test asset file src/core/selector/tests/assets/vitor-mariano@regex-tui.ron containing various asset filenames with OS and architecture labels as extensions.
  • Added new test cases to selector_tests.rs to verify correct matching for Linux x86_64 and macOS arm64 assets that use OS/arch labels as extensions.

Summary by CodeRabbit

  • Improvements
    • More accurate platform and CPU detection (expanded macOS and x86 alias handling) for better asset selection.
  • Bug Fixes
    • Stricter rejection of checksum/signature artifacts and invalid OS/architecture combinations to avoid wrong downloads.
  • New Features
    • Filename heuristics and scoring refinements to improve automated selection of matching binaries.
  • Tests
    • Extensive unit tests and new asset fixtures covering platform/arch edge cases and incompatible combos.

- support additional case
- commented out OS not supported atm
- refactor code
@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Reworks asset selection scoring in selector.rs: adds checksum/signature filtering, tokenized alias matching, OS/arch alias lookups and normalization, revised filename/extension scoring and explicit mismatch guards. Adds helper predicates in files::utils and multiple unit tests plus asset fixtures for compatibility and incompatibility cases.

Changes

Cohort / File(s) Summary
Core selector logic
src/core/selector.rs
Rewrote get_triple_score: early reject checksum/signature files, lookup-based OS and arch alias matching (with normalization and alias priorities), explicit arch/OS mismatch guards, revised filename/extension scoring and new early-return control flow.
Selector tests & fixtures
src/core/selector/tests/mod.rs, src/core/selector/tests/assets.rs, src/core/selector/tests/incompatible.rs, src/core/selector/tests/assets/*.ron
Added many unit tests for get_triple_compatible_assets and get_triple_score and new .ron asset fixtures covering macOS/Linux/Windows across multiple architectures; restructured test module exports.
File utilities
src/files/utils.rs
Added public helpers: contains_alias_token, is_checksum_file, and is_signature_file used by selector scoring to detect tokenized OS/arch aliases and to skip checksum/signature artifacts.
Utility tests
src/files/utils/tests/mod.rs, src/files/utils/tests/test_contains_alias_token.rs, src/files/utils/tests/test_is_checksum_file.rs, src/files/utils/tests/test_is_signature_file.rs
Added comprehensive unit tests for the three new utility functions and registered the test modules.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through filenames, sniff each little bit,
I skip the checksums, and nudge aliases to fit,
mac, darwin, amd64 or arm — I sort the crowd,
I nibble at extensions, and shout when matches are loud,
Tests cheer, fixtures shine — I twitch my whiskers proud. 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature being added: support for binaries that use architecture or OS names as file extensions.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/support-custom-extensions

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.

@pirafrank pirafrank changed the title feat/support custom extensions feat: support binaries with arch or OS as extension Mar 3, 2026
@pirafrank pirafrank added enhancement Suggestion of an improvement of an existing feature or functionality feature request Suggestion of a new feature or functionality labels Mar 3, 2026
@pirafrank pirafrank added this to the 0.6.1 milestone Mar 3, 2026
Copy link

@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.

🧹 Nitpick comments (2)
src/core/selector.rs (2)

167-175: Side effect inside .map() closure works but is non-idiomatic.

The pattern of mutating score inside the .map() closure works correctly since find() short-circuits, but it's unusual in Rust. Consider separating the match detection from score modification for clarity:

♻️ Optional: More idiomatic approach
-    let matching_os: Option<String> =
-        os_aliases
-            .iter()
-            .find(|alias| item.contains(*alias))
-            .map(|alias| {
-                score += 5;
-                alias.to_string()
-            });
+    let matching_os: Option<String> = os_aliases
+        .iter()
+        .find(|alias| item.contains(*alias))
+        .map(|alias| alias.to_string());
+    if matching_os.is_some() {
+        score += 5;
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/selector.rs` around lines 167 - 175, The code mutates score inside
the map closure on the iterator chain (matching_os creation), which is
non-idiomatic; change it to first find the match without side effects (use
os_aliases.iter().find(...) to set matching_os or found_os) and then, if
matching_os.is_some() (or if found_os), increment score by 5 in a separate
statement; update the variables referenced (matching_os, found_os, score,
os_aliases, item) so side effects are not performed inside the closure and
behavior remains the same.

201-219: Mutation inside find() predicate is non-idiomatic and error-prone.

Decrementing num_aliases inside the find() predicate works but mixes iteration control with side effects. The logic prioritizes earlier aliases correctly, but the code is hard to follow. Consider using enumerate() for clearer intent:

♻️ Clearer approach using enumerate
-    let mut num_aliases = arch_aliases.len();
-    let matching_arch: Option<String> = arch_aliases
+    let matching_arch: Option<(usize, String)> = arch_aliases
         .iter()
-        .find(|alias| {
-            // We iterate over the aliases in reverse order to give more priority to
-            // the more specific aliases.
-            num_aliases -= 1;
-            item.contains(*alias)
-        })
-        .map(|alias| {
-            // We also add a base 5 points bonus in case of a match, like for OS matching.
-            // Then we add the number of aliases remaining to the score to give more priority
-            // to the earlier aliases in the array.
-            // This is to avoid false positives for assets that have multiple options for
-            // the same architecture, e.g. armv7, armv6 and armhf when running on armv7.
-            score = score + 5 + (num_aliases as i32);
-            alias.to_string()
-        });
+        .enumerate()
+        .find(|(_, alias)| item.contains(*alias))
+        .map(|(idx, alias)| {
+            // Base 5 points + priority bonus for earlier aliases
+            let priority_bonus = (arch_aliases.len() - 1 - idx) as i32;
+            score += 5 + priority_bonus;
+            (idx, alias.to_string())
+        });
+    let matching_arch: Option<String> = matching_arch.map(|(_, s)| s);
     let found_arch: bool = matching_arch.is_some();
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/core/selector.rs`:
- Around line 167-175: The code mutates score inside the map closure on the
iterator chain (matching_os creation), which is non-idiomatic; change it to
first find the match without side effects (use os_aliases.iter().find(...) to
set matching_os or found_os) and then, if matching_os.is_some() (or if
found_os), increment score by 5 in a separate statement; update the variables
referenced (matching_os, found_os, score, os_aliases, item) so side effects are
not performed inside the closure and behavior remains the same.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6ed2a9 and 382a21f.

📒 Files selected for processing (3)
  • src/core/selector.rs
  • src/core/selector/tests/assets/vitor-mariano@regex-tui.ron
  • src/core/selector/tests/selector_tests.rs

@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.84%. Comparing base (1de613c) to head (779b7b3).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #183      +/-   ##
==========================================
+ Coverage   89.64%   89.84%   +0.20%     
==========================================
  Files          34       34              
  Lines        3187     3231      +44     
==========================================
+ Hits         2857     2903      +46     
+ Misses        330      328       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@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: 2

🧹 Nitpick comments (1)
src/core/selector/tests/assets.rs (1)

400-446: Strengthen the new extension tests with uniqueness checks.

These tests validate content, but not that a single best asset is selected. Add assert_eq!(binaries.len(), 1) to catch scoring ties/regressions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/selector/tests/assets.rs` around lines 400 - 446, Add assertions
that exactly one asset is selected to each new test to prevent ties/regressions:
after unwrapping the Option from get_triple_compatible_assets (in tests
test_linux_x86_64_arch_label_as_extension,
test_macos_arm64_arch_label_as_extension,
test_linux_x86_64_os_label_as_extension, test_macos_arm64_os_label_as_extension)
insert assert_eq!(binaries.len(), 1) before the contains check so you verify the
length of the binaries Vec returned for the given AssetTriple and scoring logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/selector.rs`:
- Around line 167-170: The current alias matching uses raw substring checks
(matching_os via os_aliases.iter().find(|alias| item.contains(*alias))) which is
too permissive; change it to a boundary-aware match (e.g., match whole tokens or
use word-boundary/regex checks) so aliases only match when they are separate
tokens or adjacent to common separators (-, _, ., start/end), not when embedded
in unrelated words. Update the matching logic for os_aliases -> matching_os and
the analogous arch_aliases -> matching_arch checks (the other occurrence around
the arch matching code) to use the same token/boundary-aware matching approach,
and ensure you preserve the same alias-to-string mapping (alias.to_string())
after a successful bounded match.
- Around line 231-235: The current logic grants points for any filename without
a dot (variables item and score), which is too permissive; change the condition
so that no-dot filenames only get the bonus when they are likely real
executables: implement or call a helper (e.g., is_likely_executable(item)) that
rejects common metadata/checksum names ("sha", "sha256", "checksums",
"manifest", "license", "readme", etc.) and only returns true if the base name
matches the expected executable name pattern or passes executable heuristics;
then replace the three no-dot checks (the item.contains(".") branches around the
snippets using found_arch and matching_arch at the shown location and the
similar blocks at the other occurrences) to use that helper so non-binary
metadata files no longer receive the bonus.

---

Nitpick comments:
In `@src/core/selector/tests/assets.rs`:
- Around line 400-446: Add assertions that exactly one asset is selected to each
new test to prevent ties/regressions: after unwrapping the Option from
get_triple_compatible_assets (in tests
test_linux_x86_64_arch_label_as_extension,
test_macos_arm64_arch_label_as_extension,
test_linux_x86_64_os_label_as_extension, test_macos_arm64_os_label_as_extension)
insert assert_eq!(binaries.len(), 1) before the contains check so you verify the
length of the binaries Vec returned for the given AssetTriple and scoring logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 80a3b628-a5a1-4d34-a6ee-7e2710fd42d6

📥 Commits

Reviewing files that changed from the base of the PR and between 382a21f and e01241e.

📒 Files selected for processing (6)
  • src/core/selector.rs
  • src/core/selector/tests/assets.rs
  • src/core/selector/tests/assets/fantauser@fantarepo_ends_in_os.ron
  • src/core/selector/tests/assets/pirafrank@rust_exif_renamer.ron
  • src/core/selector/tests/incompatible.rs
  • src/core/selector/tests/mod.rs
✅ Files skipped from review due to trivial changes (1)

Copy link

@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.

🧹 Nitpick comments (2)
src/files/utils.rs (1)

116-119: Handle empty aliases explicitly.

At Line 116, an empty alias can produce boundary-dependent matches through match_indices(""). Add an early return to make behavior deterministic (false for empty alias).

Proposed change
 pub fn contains_alias_token(item: &str, alias: &str) -> bool {
+    if alias.is_empty() {
+        return false;
+    }
     let item = item.to_lowercase();
     let alias = alias.to_lowercase();
     item.match_indices(&alias).any(|(start, _)| {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/files/utils.rs` around lines 116 - 119, The contains_alias_token function
should explicitly handle empty aliases to avoid match_indices("") behavior; add
an early check in contains_alias_token (e.g., if alias.is_empty() return false)
before performing the lowercase/substring checks so empty alias returns false
deterministically, then proceed with the existing logic that lowercases item and
alias and uses match_indices to test token boundaries.
src/core/selector.rs (1)

305-326: Avoid duplicate lowercasing in hot scoring path.

get_triple_score already normalizes item at Line 138, then is_checksum_file (Line 306) and is_signature_file (Line 325) lowercase again. This adds avoidable allocations per asset.

Proposed change
-fn is_checksum_file(item: &str) -> bool {
-    let item = item.to_lowercase();
+fn is_checksum_file(item: &str) -> bool {
     item == "checksum.txt"
         || item == "checksums.txt"
         || item.ends_with(".sha256")
@@
-fn is_signature_file(item: &str) -> bool {
-    let item = item.to_lowercase();
+fn is_signature_file(item: &str) -> bool {
     item.ends_with(".asc")
         || item.ends_with(".sig")
         || item.ends_with(".pem")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/selector.rs` around lines 305 - 326, Summary: get_triple_score
already normalizes item once, so remove duplicate lowercasing inside
is_checksum_file and is_signature_file to avoid extra allocations; modify these
functions to assume they receive an already lowercased &str (remove the
to_lowercase() calls and operate directly on the &str) and update their callers
(notably get_triple_score which normalizes item at Line 138) to pass the
normalized string slice into is_checksum_file and is_signature_file. Ensure
function signatures remain &str inputs and only one lowercase allocation happens
in get_triple_score.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/core/selector.rs`:
- Around line 305-326: Summary: get_triple_score already normalizes item once,
so remove duplicate lowercasing inside is_checksum_file and is_signature_file to
avoid extra allocations; modify these functions to assume they receive an
already lowercased &str (remove the to_lowercase() calls and operate directly on
the &str) and update their callers (notably get_triple_score which normalizes
item at Line 138) to pass the normalized string slice into is_checksum_file and
is_signature_file. Ensure function signatures remain &str inputs and only one
lowercase allocation happens in get_triple_score.

In `@src/files/utils.rs`:
- Around line 116-119: The contains_alias_token function should explicitly
handle empty aliases to avoid match_indices("") behavior; add an early check in
contains_alias_token (e.g., if alias.is_empty() return false) before performing
the lowercase/substring checks so empty alias returns false deterministically,
then proceed with the existing logic that lowercases item and alias and uses
match_indices to test token boundaries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3afa4d1-ea71-43cb-8962-618e68deb0d6

📥 Commits

Reviewing files that changed from the base of the PR and between e01241e and 0673ed9.

📒 Files selected for processing (4)
  • src/core/selector.rs
  • src/files/utils.rs
  • src/files/utils/tests/mod.rs
  • src/files/utils/tests/test_contains_alias_token.rs

Copy link

@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.

🧹 Nitpick comments (3)
src/core/selector.rs (1)

10-21: Commented-out code for unsupported OSes is acceptable.

Per retrieved learnings, Windows is not supported in this project. The BSD entries are also commented out, which is fine if poof doesn't target those platforms. Consider adding a brief comment explaining why these are disabled (e.g., // Currently unsupported platforms) for future maintainability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/selector.rs` around lines 10 - 21, The commented-out OS entries in
the lazy_static OPERATING_SYSTEM hashmap (symbol OPERATING_SYSTEM in
selector.rs) lack an explanatory note; add a brief clarifying comment above or
next to the commented entries (e.g., “// Currently unsupported platforms:
windows, openbsd, freebsd, netbsd”) so future readers understand these platforms
are intentionally disabled rather than accidentally left commented out. Ensure
the comment references the disabled platforms by name and sits near the
m.insert(...) lines for visibility.
src/files/utils.rs (2)

237-246: Consider whether .pem is appropriate for signature detection.

.pem files are typically certificates or private keys, not signatures. Including them may cause false positives for legitimate PEM-encoded assets (e.g., CA bundles, TLS certs distributed alongside tools).

Common signature-only extensions are: .asc, .sig, .minisig, .pgp, .gpg.

🔧 Suggested fix
 pub fn is_signature_file(item: &str) -> bool {
     let item = item.to_lowercase();
     item.ends_with(".asc")
         || item.ends_with(".sig")
-        || item.ends_with(".pem")
         || item.ends_with(".minisign")
         || item.ends_with(".pgp")
         || item.ends_with(".gpg")
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/files/utils.rs` around lines 237 - 246, The is_signature_file function
currently treats ".pem" as a signature which causes false positives; update the
function to remove the ".pem" check and ensure the signature extensions list
uses the correct common names (replace ".minisign" with ".minisig" if needed) —
modify the checks in pub fn is_signature_file(item: &str) to only match known
signature extensions (".asc", ".sig", ".minisig" or ".minisign" consistent with
project conventions, ".pgp", ".gpg") and run/update any tests that assert
signature detection behavior accordingly.

218-235: Consider adding additional checksum patterns.

Some projects use different naming conventions for checksum files that aren't covered:

  • SHASUMS, SHA256SUMS, SHA512SUMS (common in Node.js releases)
  • .b2sum, .blake2 (Blake2 checksums)
  • Files containing "digest" in the name

This is optional and can be deferred if current coverage meets project needs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/files/utils.rs` around lines 218 - 235, The is_checksum_file function
currently misses several common patterns; update is_checksum_file to also detect
names like "shasums", "sha256sums", "sha512sums" (accounting for the existing
to_lowercase), add checks for Blake2 extensions (e.g., ends_with(".b2sum") and
ends_with(".blake2")), and consider a contains("digest") check to catch files
with "digest" in the name; modify the function's boolean expressions (or
refactor to a small iterator over patterns) to include these new patterns while
keeping the initial to_lowercase call and existing checks (function:
is_checksum_file).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/core/selector.rs`:
- Around line 10-21: The commented-out OS entries in the lazy_static
OPERATING_SYSTEM hashmap (symbol OPERATING_SYSTEM in selector.rs) lack an
explanatory note; add a brief clarifying comment above or next to the commented
entries (e.g., “// Currently unsupported platforms: windows, openbsd, freebsd,
netbsd”) so future readers understand these platforms are intentionally disabled
rather than accidentally left commented out. Ensure the comment references the
disabled platforms by name and sits near the m.insert(...) lines for visibility.

In `@src/files/utils.rs`:
- Around line 237-246: The is_signature_file function currently treats ".pem" as
a signature which causes false positives; update the function to remove the
".pem" check and ensure the signature extensions list uses the correct common
names (replace ".minisign" with ".minisig" if needed) — modify the checks in pub
fn is_signature_file(item: &str) to only match known signature extensions
(".asc", ".sig", ".minisig" or ".minisign" consistent with project conventions,
".pgp", ".gpg") and run/update any tests that assert signature detection
behavior accordingly.
- Around line 218-235: The is_checksum_file function currently misses several
common patterns; update is_checksum_file to also detect names like "shasums",
"sha256sums", "sha512sums" (accounting for the existing to_lowercase), add
checks for Blake2 extensions (e.g., ends_with(".b2sum") and
ends_with(".blake2")), and consider a contains("digest") check to catch files
with "digest" in the name; modify the function's boolean expressions (or
refactor to a small iterator over patterns) to include these new patterns while
keeping the initial to_lowercase call and existing checks (function:
is_checksum_file).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5c933696-be50-4311-b716-50380885725f

📥 Commits

Reviewing files that changed from the base of the PR and between 0673ed9 and 8efe4f0.

📒 Files selected for processing (6)
  • src/core/selector.rs
  • src/files/utils.rs
  • src/files/utils/tests/mod.rs
  • src/files/utils/tests/test_contains_alias_token.rs
  • src/files/utils/tests/test_is_checksum_file.rs
  • src/files/utils/tests/test_is_signature_file.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/files/utils/tests/test_contains_alias_token.rs
  • src/files/utils/tests/mod.rs

Copy link

@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.

🧹 Nitpick comments (2)
src/core/selector/tests/assets.rs (2)

412-458: Strengthen single-match assertions to avoid false positives.

In these tests, Line 420/432/444/456 unwrap and then only check binaries[0]. Please also assert len() == 1 so regressions that return extra matches are caught.

Proposed tightening
         assert!(binaries.is_some());
         let binaries = binaries.unwrap();
+        assert_eq!(binaries.len(), 1);
         assert!(binaries[0].contains("regex-tui_v0.7.0_linux.amd64"));
@@
         assert!(binaries.is_some());
         let binaries = binaries.unwrap();
+        assert_eq!(binaries.len(), 1);
         assert!(binaries[0].contains("regex-tui_v0.7.0_darwin.arm64"));
@@
         assert!(binaries.is_some());
         let binaries = binaries.unwrap();
+        assert_eq!(binaries.len(), 1);
         assert!(binaries[0].contains("fantarepo_ends_in_os_v1.0.0_amd64.linux"));
@@
         assert!(binaries.is_some());
         let binaries = binaries.unwrap();
+        assert_eq!(binaries.len(), 1);
         assert!(binaries[0].contains("fantarepo_ends_in_os_v1.0.0_arm64.darwin"));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/selector/tests/assets.rs` around lines 412 - 458, The tests calling
get_triple_compatible_assets currently unwrap the Option and only assert on
binaries[0], which allows extra matches to slip by; update each test (those
using AssetTriple in test_linux_x86_64_arch_label_as_extension,
test_macos_arm64_arch_label_as_extension,
test_linux_x86_64_os_label_as_extension, test_macos_arm64_os_label_as_extension)
to assert that binaries.len() == 1 immediately after unwrap() before checking
binaries[0]. This ensures exactly one match is returned and prevents false
positives from additional results.

460-482: Make multi-asset checks order-independent.

Line 468-469 and Line 480-481 assume stable ordering. Since these tests validate membership, prefer order-agnostic assertions to reduce brittleness.

Order-agnostic variant
         assert!(!binaries.is_empty() && binaries.len() == 2);
-        assert!(binaries[0].contains("kubectx_v0.9.5_linux_x86_64.tar.gz"));
-        assert!(binaries[1].contains("kubens_v0.9.5_linux_x86_64.tar.gz"));
+        assert!(binaries
+            .iter()
+            .any(|b| b.contains("kubectx_v0.9.5_linux_x86_64.tar.gz")));
+        assert!(binaries
+            .iter()
+            .any(|b| b.contains("kubens_v0.9.5_linux_x86_64.tar.gz")));
@@
         assert!(!binaries.is_empty() && binaries.len() == 2);
-        assert!(binaries[0].contains("kubectx_v0.9.5_linux_armv7.tar.gz"));
-        assert!(binaries[1].contains("kubens_v0.9.5_linux_armv7.tar.gz"));
+        assert!(binaries
+            .iter()
+            .any(|b| b.contains("kubectx_v0.9.5_linux_armv7.tar.gz")));
+        assert!(binaries
+            .iter()
+            .any(|b| b.contains("kubens_v0.9.5_linux_armv7.tar.gz")));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/selector/tests/assets.rs` around lines 460 - 482, The tests
test_linux_x86_64_multiple_assets and test_linux_armv7_multiple_assets rely on
stable ordering of the returned Vec in get_triple_compatible_assets; change the
assertions to be order-independent by asserting membership of both expected
filenames rather than exact positions — e.g., unwrap binaries, ensure
binaries.len() == 2 (or >=2 if appropriate), then check that the collection
contains "kubectx_v0.9.5_linux_x86_64.tar.gz" and
"kubens_v0.9.5_linux_x86_64.tar.gz" (and the armv7 variants) using contains or
by converting to a HashSet and asserting both expected strings are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/core/selector/tests/assets.rs`:
- Around line 412-458: The tests calling get_triple_compatible_assets currently
unwrap the Option and only assert on binaries[0], which allows extra matches to
slip by; update each test (those using AssetTriple in
test_linux_x86_64_arch_label_as_extension,
test_macos_arm64_arch_label_as_extension,
test_linux_x86_64_os_label_as_extension, test_macos_arm64_os_label_as_extension)
to assert that binaries.len() == 1 immediately after unwrap() before checking
binaries[0]. This ensures exactly one match is returned and prevents false
positives from additional results.
- Around line 460-482: The tests test_linux_x86_64_multiple_assets and
test_linux_armv7_multiple_assets rely on stable ordering of the returned Vec in
get_triple_compatible_assets; change the assertions to be order-independent by
asserting membership of both expected filenames rather than exact positions —
e.g., unwrap binaries, ensure binaries.len() == 2 (or >=2 if appropriate), then
check that the collection contains "kubectx_v0.9.5_linux_x86_64.tar.gz" and
"kubens_v0.9.5_linux_x86_64.tar.gz" (and the armv7 variants) using contains or
by converting to a HashSet and asserting both expected strings are present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d1f3b99d-de44-4c96-bce7-9a5169919be0

📥 Commits

Reviewing files that changed from the base of the PR and between 8efe4f0 and d27554c.

📒 Files selected for processing (1)
  • src/core/selector/tests/assets.rs

@pirafrank pirafrank merged commit aaf1279 into main Mar 4, 2026
25 checks passed
@pirafrank pirafrank deleted the feat/support-custom-extensions branch March 4, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Suggestion of an improvement of an existing feature or functionality feature request Suggestion of a new feature or functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant