Skip to content

feat(vfox): add RUNTIME.envType for libc variant detection#8493

Merged
jdx merged 6 commits intojdx:mainfrom
malept:feat/vfox-runtime-envtype
Mar 7, 2026
Merged

feat(vfox): add RUNTIME.envType for libc variant detection#8493
jdx merged 6 commits intojdx:mainfrom
malept:feat/vfox-runtime-envtype

Conversation

@malept
Copy link
Copy Markdown
Contributor

@malept malept commented Mar 7, 2026

Summary

Expose the libc type detection added in #8490 to vfox plugins, in the RUNTIME global table.

Details

  • Expose RUNTIME.envType to vfox Lua plugins ("gnu" for glibc Linux, "musl" for musl Linux, nil otherwise)
  • Add env_type() in crates/vfox/src/config.rs to detect libc at runtime via /lib and /lib64 linker names
  • Add sync-note comments in crates/vfox/src/config.rs and src/platform.rs to keep both implementations aligned
  • Set env_type to None in Runtime::with_platform() because target libc is unknown for platform overrides
  • Document RUNTIME.envType in Lua types and plugin docs
  • Add missing RUNTIME.version and RUNTIME.pluginDirPath entries to docs/tool-plugin-development.md for parity

Usage in plugins

if RUNTIME.envType == "musl" then
    -- download musl-compatible binary
elseif RUNTIME.envType == "gnu" then
    -- download glibc-compatible binary
end

Design decisions

We intentionally duplicate musl/glibc detection in crates/vfox because vfox is a separate crate boundary and sharing is_musl_system() would add unnecessary coupling. The logic is small, self-contained, and cross-referenced by sync notes in both locations to reduce drift.

Test plan

  • Unit tests for env_type() return only valid values ("gnu", "musl", or nil) on Linux and nil on non-Linux
  • Added regression test ensuring RUNTIME.envType is nil when using platform override (Runtime::with_platform)
  • cargo test passes
  • Lint passes (mise --cd crates/vfox run lint-fix)

🤖 This PR description was generated with the assistance of Claude Opus 4.6.

malept added 4 commits March 7, 2026 00:29
Add env_type() function in crates/vfox/src/config.rs that detects the
libc environment type at runtime on Linux by scanning /lib and /lib64
for the dynamic linker (ld-linux-* for glibc, ld-musl-* for musl).
Returns Some("gnu"), Some("musl"), or None on non-Linux platforms.

Add cross-reference comments to both is_musl_system() in src/platform.rs
and env_type() in crates/vfox/src/config.rs to keep the duplicated
logic in sync.

Assisted-By: Claude Opus 4.6 via GitHub Copilot
Add env_type: Option<String> field to the vfox Runtime struct, populated
from the env_type() helper added in the previous commit. Exposed to Lua
plugins as RUNTIME.envType — returns "gnu" on glibc Linux, "musl" on
musl Linux, and nil on all other platforms.

Runtime::with_platform() sets env_type to None since the target libc
variant is unknown in cross-platform URL generation context.

Add set_env_type() test helper and update reset() to restore env_type.

Assisted-By: Claude Opus 4.6 via GitHub Copilot
Add RUNTIME.envType to the Lua type definitions in mise-plugin.lua and
to the RUNTIME reference sections in both backend-plugin-development.md
and tool-plugin-development.md.

Also add previously missing RUNTIME.version and RUNTIME.pluginDirPath
entries to tool-plugin-development.md for parity with
backend-plugin-development.md.

Assisted-By: Claude Opus 4.6 via GitHub Copilot
Relax Linux env_type test to allow None when libc detection is unavailable,
matching the documented contract.

Add a runtime regression test to assert RUNTIME.envType is nil when
RUNTIME is overridden via Runtime::with_platform for cross-platform hook
execution.

Assisted-By: GPT-5.3-Codex via GitHub Copilot
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the vfox runtime by exposing the detected libc environment type (glibc or musl) to Lua plugins via a new RUNTIME.envType field. This enables plugins to dynamically adapt their behavior, such as downloading appropriate binaries, based on the underlying Linux system's libc implementation. The change involves adding a new detection mechanism, integrating it into the runtime, and updating relevant documentation and tests.

Highlights

  • New RUNTIME.envType for Libc Detection: Introduced RUNTIME.envType to vfox Lua plugins, allowing detection of the libc variant (glibc or musl) on Linux systems. This enables plugins to adapt their behavior based on the underlying libc implementation.
  • Libc Detection Logic: Implemented a new env_type() function in crates/vfox/src/config.rs for runtime libc detection. This function identifies glibc or musl by checking for the presence of specific dynamic linker files (ld-linux-* or ld-musl-*).
  • Documentation Updates: Updated documentation for both backend-plugin-development.md and tool-plugin-development.md to reflect the new RUNTIME.envType field. Additionally, RUNTIME.version and RUNTIME.pluginDirPath were added to tool-plugin-development.md for consistency.
  • Platform Override Handling: Added a regression test to verify that RUNTIME.envType is correctly set to nil when using platform overrides, ensuring that libc detection is not applied in cross-platform contexts where it is not applicable.
Changelog
  • crates/vfox/src/config.rs
    • Added env_type() function to detect glibc or musl on Linux, returning "gnu", "musl", or None.
    • Included has_file_prefix helper function for file system checks.
    • Added unit tests for the new env_type() function.
  • crates/vfox/src/hooks/pre_install.rs
    • Added a new test case test_runtime_env_type_is_nil_for_platform_override to ensure RUNTIME.envType is nil when a platform override is active.
  • crates/vfox/src/runtime.rs
    • Imported env_type from config.rs.
    • Added env_type: Option<String> field to the Runtime struct.
    • Initialized env_type in the RUNTIME static lazy initializer.
    • Set runtime.env_type to None in Runtime::with_platform for cross-platform contexts.
    • Added set_env_type for testing purposes.
    • Updated reset function to also reset env_type.
    • Exposed envType via UserDataFields for Lua access.
  • crates/vfox/types/mise-plugin.lua
    • Added ---@field envType string|nil to the ---@class Runtime definition.
  • docs/backend-plugin-development.md
    • Added RUNTIME.envType to the list of available RUNTIME properties.
  • docs/tool-plugin-development.md
    • Added RUNTIME.envType, RUNTIME.version, and RUNTIME.pluginDirPath to the list of available RUNTIME properties.
  • src/platform.rs
    • Added a NOTE comment to is_musl_system() referencing the mirrored logic in crates/vfox/src/config.rs.
Activity
  • The pull request author has implemented the feature, including libc detection, runtime integration, documentation updates, and new tests.
  • The author has verified the changes by running unit tests, lint checks, and a regression test for platform overrides.
  • The PR description was generated with the assistance of Claude Opus 4.6.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 7, 2026

Greptile Summary

This PR exposes the libc variant detection introduced in #8490 to vfox Lua plugins via a new RUNTIME.envType field ("gnu", "musl", or nil). The implementation is clean and the design decision to duplicate the detection logic within the vfox crate boundary (rather than sharing it with src/platform.rs) is explicitly documented and justified.

Key changes:

  • env_type() is added to crates/vfox/src/config.rs, mirroring the is_musl_system() logic in src/platform.rs with cross-reference sync-notes in both files.
  • Runtime gains an env_type: Option<String> field, initialised from env_type() on startup and forced to None in Runtime::with_platform() (correct, since target libc is unknown for platform overrides).
  • RUNTIME.envType is exposed via mlua::UserData, with Option<String> naturally mapping to string|nil in Lua.
  • LuaCATS types, and both plugin-development doc pages are updated, including back-filling previously missing RUNTIME.version and RUNTIME.pluginDirPath entries in tool-plugin-development.md.
  • Tests correctly accept None as a valid env_type return on Linux (fixing the brittle assertion noted in prior review threads) and a new integration test verifies the with_platform() nil contract.

Minor style observations:

  • config.rs uses once_cell::sync::Lazy while the mirrored src/platform.rs uses std::sync::LazyLock; aligning on the stdlib type would make the "keep in sync" comment easier to follow.
  • The new integration test (and existing tests) mutate the global RUNTIME singleton without panic-safe cleanup; a scopeguard defer or similar would make resets unconditional.

Confidence Score: 4/5

  • This PR is safe to merge; all identified issues are style-level with no functional or correctness impact.
  • The logic is small and self-contained, mirrors an already-reviewed implementation, tests cover the main behavioural contract (including the cross-platform override nil case), and documentation is complete. The two minor points — inconsistent lazy-init primitive and non-panic-safe test teardown — are stylistic and consistent with the rest of the codebase.
  • No files require special attention; the two style observations are in crates/vfox/src/config.rs and crates/vfox/src/hooks/pre_install.rs.

Important Files Changed

Filename Overview
crates/vfox/src/config.rs Adds env_type() with once_cell::sync::Lazy-backed caching to detect libc variant at runtime; logic correctly mirrors is_musl_system() in src/platform.rs; test suite correctly accepts None as a valid return value.
crates/vfox/src/runtime.rs Adds env_type: Option<String> field to Runtime, initialises it from env_type(), exposes it as the envType Lua field, and correctly sets it to None in with_platform(). The reset() helper is extended consistently. Minor: plugin_dir_path and version are still not reset in reset(), but that is pre-existing behaviour outside this PR.
crates/vfox/src/hooks/pre_install.rs New integration test verifies that RUNTIME.envType is nil for a platform-override Runtime. Logic is correct; test properly calls Runtime::reset() at the end. One minor concern: set_env_type(Some("gnu")) is called unconditionally regardless of host platform, but the test is only asserting cross-platform override semantics, so this is intentional.
crates/vfox/types/mise-plugin.lua Adds correct `---@field envType string
docs/backend-plugin-development.md Adds RUNTIME.envType documentation entry; wording is accurate and consistent with the implementation.
docs/tool-plugin-development.md Adds RUNTIME.envType, RUNTIME.version, and RUNTIME.pluginDirPath entries, filling previously missing documentation gaps.
src/platform.rs Only change is a sync-note comment on is_musl_system(); no logic changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[env_type called] --> B{target_os = linux?}
    B -- No --> C[return None]
    B -- Yes --> D{/lib or /lib64 contains ld-linux-* ?}
    D -- Yes --> E[return Some-gnu]
    D -- No --> F{/lib contains ld-musl-* ?}
    F -- Yes --> G[return Some-musl]
    F -- No --> H[return None]

    subgraph Runtime Initialisation
        I[Runtime::new] --> J[env_type = env_type]
        K[Runtime::with_platform] --> L[env_type = None\ntarget libc unknown]
    end

    subgraph Lua Exposure
        M[RUNTIME.envType] --> N{env_type value}
        N -- Some-gnu --> O[Lua string 'gnu']
        N -- Some-musl --> P[Lua string 'musl']
        N -- None --> Q[Lua nil]
    end
Loading

Last reviewed commit: 118ebf4

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces RUNTIME.envType to expose libc variant detection to vfox plugins, which is a valuable addition for creating platform-specific logic. The implementation is well-executed, with the core detection logic in crates/vfox/src/config.rs being efficient and correctly memoized. The changes are consistently applied across the runtime, documentation, and type definitions. I particularly appreciate the new test case that verifies the behavior for platform overrides, ensuring robustness. Overall, this is a high-quality contribution.

Make test_env_type_linux_is_valid meaningfully stricter than the
cross-platform test_env_type by asserting env_type() returns Some("gnu")
or Some("musl") on Linux, rather than also accepting None.

Assisted-By: Claude Opus 4.6 <noreply@anthropic.com>
…dard systems

Drop test_env_type_linux_is_valid since it would break for contributors
on Linux systems without standard glibc/musl linker paths (e.g., minimal
containers, statically-linked setups). The cross-platform test_env_type
already validates all valid return values.

Assisted-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment on lines +51 to +67
pub(crate) fn env_type() -> Option<String> {
use once_cell::sync::Lazy;
static ENV_TYPE: Lazy<Option<String>> = Lazy::new(|| {
// If glibc's dynamic linker exists, this is a glibc system
for dir in ["/lib", "/lib64"] {
if has_file_prefix(dir, "ld-linux-") {
return Some("gnu".to_string());
}
}
// No glibc linker found — check for musl's
if has_file_prefix("/lib", "ld-musl-") {
return Some("musl".to_string());
}
None
});
ENV_TYPE.clone()
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

once_cell::Lazy vs stdlib LazyLock

The src/platform.rs counterpart uses std::sync::LazyLock (stable since Rust 1.80), while this implementation uses once_cell::sync::Lazy imported inline. Because the vfox crate already depends on once_cell elsewhere (runtime.rs uses it at the module level), there is no new dependency concern — but the two "mirrored" implementations now rely on different lazy-init primitives, which adds a subtle inconsistency for anyone reading both files side-by-side.

If the MSRV allows it, aligning on std::sync::LazyLock would match platform.rs exactly:

use std::sync::LazyLock;
static ENV_TYPE: LazyLock<Option<String>> = LazyLock::new(|| {
    // …same body…
});

This is purely a style/consistency observation; both approaches are functionally identical.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

RUNTIME itself is using once_cell::Lazy:

static RUNTIME: Lazy<Mutex<Runtime>> = Lazy::new(|| {
Mutex::new(Runtime {
os: os(),
arch: arch(),
version: "0.6.0".to_string(), // https://github.com/version-fox/vfox/releases
plugin_dir_path: PathBuf::new(),
})
});

(As does SDKS.)

If anything, this should be refactored in a separate PR.

Comment on lines +252 to +288
#[test]
async fn test_runtime_env_type_is_nil_for_platform_override() {
let plugin = Plugin::test("dummy");

Runtime::set_env_type(Some("gnu".to_string()));

let host_env_type: Option<String> = plugin
.eval_async(chunk! {
return RUNTIME.envType
})
.await
.unwrap();
assert_eq!(host_env_type, Some("gnu".to_string()));

let target_runtime = Runtime::with_platform(plugin.dir.clone(), "linux", "amd64");
let target_os = "linux".to_string();
let target_arch = "amd64".to_string();
let target_env_type: Option<String> = plugin
.eval_async(chunk! {
local saved_os = OS_TYPE
local saved_arch = ARCH_TYPE
local saved_runtime = RUNTIME
OS_TYPE = $target_os
ARCH_TYPE = $target_arch
RUNTIME = $target_runtime
local env_type = RUNTIME.envType
OS_TYPE = saved_os
ARCH_TYPE = saved_arch
RUNTIME = saved_runtime
return env_type
})
.await
.unwrap();
assert_eq!(target_env_type, None);

Runtime::reset();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Test does not guard against panic before Runtime::reset()

Runtime::set_env_type(Some("gnu".to_string())) mutates the process-wide RUNTIME singleton. If the test panics between that call and Runtime::reset() at line 287, the global state is left dirty and can affect other tests running in the same process.

The existing pattern in this file (e.g., test_linux_arm64_and_windows_x64) has the same issue, so this is not unique to this PR. However, since a new test is being added here it is worth noting. A scopeguard-style defer, or wrapping the body in a closure with std::panic::catch_unwind, would make the reset unconditional:

let _guard = scopeguard::defer(|| Runtime::reset());

Alternatively, a Drop wrapper around the mutation would achieve the same effect.

This is low priority given that cargo test passes and the existing tests follow the same pattern.

@jdx jdx merged commit 15d4aaf into jdx:main Mar 7, 2026
36 checks passed
jdx pushed a commit that referenced this pull request Mar 7, 2026
### 🚀 Features

- **(vfox)** add `RUNTIME.envType` for libc variant detection by @malept
in [#8493](#8493)
- store provenance verification results in lockfile by @jdx in
[#8495](#8495)

### 🐛 Bug Fixes

- **(env)** skip remote version fetching for "latest" in prefer-offline
mode by @jdx in [#8500](#8500)
- **(tasks)** deduplicate shared deps across task delegation by
@vadimpiven in [#8497](#8497)
- **(windows)** correctly identify mise binary without extension by @jdx
in [#8503](#8503)

### 🚜 Refactor

- **(core)** migrate cmd! callers to async with kill_on_drop by @jdx in
[a63f7d2](a63f7d2)

### Chore

- **(ci)** temporarily disable `mise up` in release-plz by @jdx in
[#8504](#8504)
- consolidate all linters into hk.pkl by @jdx in
[#8498](#8498)

## 📦 Aqua Registry Updates

#### New Packages (1)

- [`apache/ant`](https://github.com/apache/ant)
@malept malept deleted the feat/vfox-runtime-envtype branch March 13, 2026 15:45
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.

2 participants