Skip to content

nh-installable: init#684

Open
faukah wants to merge 2 commits into
masterfrom
faukah/push-vurxnuttztyu
Open

nh-installable: init#684
faukah wants to merge 2 commits into
masterfrom
faukah/push-vurxnuttztyu

Conversation

@faukah

@faukah faukah commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Move installable resolution out of nh-core and into nh-installable. More and more crates depend on nh-installable, and separating it from nh-core is easy. I'd argue this is a good choice because it's well-separated from other functionality/behavior.

Also makes implementing nh diff easier/cleaner.

Sanity Checking

  • I have read and understood the contribution guidelines
  • I have updated the changelog as per my changes
  • I have tested, and self-reviewed my code
  • Style and consistency
    • I ran nix fmt to format my Nix code
    • I ran cargo fmt to format my Rust code
    • I have added appropriate documentation to new code
    • My changes are consistent with the rest of the codebase
  • Correctness
    • I ran cargo clippy and fixed any new linter warnings.
  • If new changes are particularly complex:
    • My code includes comments in particularly complex areas to explain the
      logic
    • I have documented the motive for those changes in the PR body or commit
      description.
  • Tested on platform(s):
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin

Add a 👍 reaction to pull requests you find important.

@faukah faukah added the allow-no-changelog Doesen't need a CHANGELOG.md entry. label Jun 10, 2026
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This pull request extracts the Installable type and its resolution logic from nh-core into a new standalone nh-installable crate. The refactored API exposes resolve_or_default as the primary public method while making internal resolution helpers and implementation details private. All dependent crates are updated to import from the new crate and to use the simplified resolution method.

Changes

Installable extraction and API refactoring

Layer / File(s) Summary
New nh-installable crate with refactored API
crates/nh-installable/Cargo.toml, crates/nh-installable/src/lib.rs
New nh-installable crate manifest and refactored Installable type: parse_attribute and resolve methods made private, new public resolve_or_default method added, helper functions try_find_default_for_os/home/darwin made private, join_attribute quoting adjusted, test suite extracted to separate module.
Comprehensive test suite for resolve_or_default behavior
crates/nh-installable/src/tests.rs
New test module with EnvGuard utility for environment variable isolation; tests validate resolve_or_default across Os, Home, Darwin contexts; verifies env variable precedence (context-specific over generic), fallback behavior, attribute parsing, and command-context isolation.
Update nh-core to use new nh-installable crate
crates/nh-core/Cargo.toml, crates/nh-core/src/lib.rs, crates/nh-core/src/args.rs, crates/nh-core/src/command.rs, crates/nh-core/src/update.rs, crates/nh-core/src/util.rs
nh-core removes installable module from public exports; all modules (args, command, update, util) updated to import Installable from nh_installable; function signatures in update and util now use nh_installable::Installable; update function documentation expanded with error handling details.
Update nh-darwin to use resolve_or_default
crates/nh-darwin/Cargo.toml, crates/nh-darwin/src/args.rs, crates/nh-darwin/src/darwin.rs
nh-darwin adds nh-installable dependency; imports updated to source Installable from nh_installable; Darwin rebuild and REPL resolution changed from resolve(CommandContext::Darwin) plus manual Installable::Unspecified fallback to single resolve_or_default(CommandContext::Darwin) call.
Update nh-home to use resolve_or_default
crates/nh-home/Cargo.toml, crates/nh-home/src/args.rs, crates/nh-home/src/home.rs
nh-home adds nh-installable dependency; imports updated to source Installable and CommandContext from nh_installable; Home rebuild and REPL resolution changed from resolve(CommandContext::Home) plus manual fallback to single resolve_or_default(CommandContext::Home) call.
Update nh-nixos to use resolve_or_default
crates/nh-nixos/Cargo.toml, crates/nh-nixos/src/args.rs, crates/nh-nixos/src/nixos.rs
nh-nixos adds nh-installable dependency; imports updated to source Installable and CommandContext from nh_installable; OS rebuild, build-image, and REPL resolution changed from resolve(CommandContext::Os) plus manual fallback to single resolve_or_default(CommandContext::Os) call.
Update nh-remote and workspace dependencies
Cargo.toml, crates/nh-remote/Cargo.toml, crates/nh-remote/src/remote.rs
nh-remote adds nh-installable dependency and updates remote.rs to import Installable from nh_installable; root workspace Cargo.toml dependencies reformatted for consistency.

Possibly related PRs

  • nix-community/nh#550: Centralizes installable resolution by CommandContext, dropping env-var state passing, which aligns directly with this PR's adoption of resolve_or_default.

  • nix-community/nh#486: Introduces the original Unspecified handling and default-resolution API that this PR builds upon by creating the dedicated nh_installable crate.

  • nix-community/nh#528: Introduces get_build_image_variants helpers that this PR updates to use nh_installable::Installable type.

Suggested reviewers

  • NotAShelf
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'nh-installable: init' directly corresponds to the main objective of creating and initializing a new nh-installable crate by extracting installable resolution functionality from nh-core.
Description check ✅ Passed The description clearly explains the purpose of the PR: moving installable resolution from nh-core into a new nh-installable crate, and notes it simplifies nh diff implementation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

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


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/nh-installable/src/tests.rs (1)

1-363: ⚡ Quick win

Consider adding test coverage for NH_FILE resolution and error cases.

The test suite comprehensively covers flake-based environment variable resolution and precedence, but two areas lack coverage:

  1. NH_FILE resolution: The code at lib.rs:318-326 handles NH_FILE (with optional NH_ATTRP), but no tests exercise this path.
  2. Error cases: Malformed environment variables (e.g., NH_FLAKE without a reference part) should return errors (lib.rs:303-314, 332-343), but no tests verify this behavior.
Example test additions
#[test]
#[serial]
fn test_resolve_uses_nh_file() {
  let env_guard = EnvGuard::clear();
  env_guard.set("NH_FILE", "/path/to/config.nix");
  env_guard.set("NH_ATTRP", "system.config");

  let resolved = Installable::Unspecified
    .resolve(CommandContext::Os)
    .unwrap();
  match resolved {
    Installable::File { path, attribute } => {
      assert_eq!(path, PathBuf::from("/path/to/config.nix"));
      assert_eq!(attribute, vec!["system", "config"]);
    },
    _ => panic!("Expected File, got {resolved:?}"),
  }
}

#[test]
#[serial]
fn test_resolve_errors_on_malformed_nh_flake() {
  let env_guard = EnvGuard::clear();
  env_guard.set("NH_FLAKE", "`#missing-reference`");

  let result = Installable::Unspecified.resolve(CommandContext::Os);
  assert!(result.is_err());
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/nh-installable/src/tests.rs` around lines 1 - 363, Add tests
exercising NH_FILE and malformed-env error paths: create serial tests similar to
existing ones that use EnvGuard::clear() and env_guard.set to set NH_FILE and
NH_ATTRP and then call Installable::Unspecified.resolve(CommandContext::Os)
asserting it returns Installable::File with expected PathBuf and attribute
vector (split on '.'); and add tests that set malformed values (e.g.,
NH_FLAKE="`#missing-reference`" and NH_FILE="`#bad`") and assert
Installable::Unspecified.resolve(...) returns an Err; reference the existing
helpers and behavior around Installable::Unspecified.resolve, EnvGuard, and
attribute parsing to mirror the style of tests like
test_resolve_with_nested_attribute and
test_resolve_no_env_vars_returns_unspecified.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/nh-installable/src/tests.rs`:
- Around line 1-363: Add tests exercising NH_FILE and malformed-env error paths:
create serial tests similar to existing ones that use EnvGuard::clear() and
env_guard.set to set NH_FILE and NH_ATTRP and then call
Installable::Unspecified.resolve(CommandContext::Os) asserting it returns
Installable::File with expected PathBuf and attribute vector (split on '.'); and
add tests that set malformed values (e.g., NH_FLAKE="`#missing-reference`" and
NH_FILE="`#bad`") and assert Installable::Unspecified.resolve(...) returns an Err;
reference the existing helpers and behavior around
Installable::Unspecified.resolve, EnvGuard, and attribute parsing to mirror the
style of tests like test_resolve_with_nested_attribute and
test_resolve_no_env_vars_returns_unspecified.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3e86c7dd-120c-4174-883a-1f8b30d2eef6

📥 Commits

Reviewing files that changed from the base of the PR and between 41e8ead and 8a77374.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • Cargo.toml
  • crates/nh-core/Cargo.toml
  • crates/nh-core/src/args.rs
  • crates/nh-core/src/command.rs
  • crates/nh-core/src/lib.rs
  • crates/nh-core/src/update.rs
  • crates/nh-core/src/util.rs
  • crates/nh-darwin/Cargo.toml
  • crates/nh-darwin/src/args.rs
  • crates/nh-darwin/src/darwin.rs
  • crates/nh-home/Cargo.toml
  • crates/nh-home/src/args.rs
  • crates/nh-home/src/home.rs
  • crates/nh-installable/Cargo.toml
  • crates/nh-installable/src/lib.rs
  • crates/nh-installable/src/tests.rs
  • crates/nh-nixos/Cargo.toml
  • crates/nh-nixos/src/args.rs
  • crates/nh-nixos/src/nixos.rs
  • crates/nh-remote/Cargo.toml
  • crates/nh-remote/src/remote.rs
💤 Files with no reviewable changes (1)
  • crates/nh-core/src/lib.rs

@NotAShelf

Copy link
Copy Markdown
Member

needs to be rebased @faukah

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

allow-no-changelog Doesen't need a CHANGELOG.md entry.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants