darwin: fix activation without darwin-rebuild
As part of supporting the new nix-darwin activation style in https://github.com/nix-community/nh/pull/238, there was a breaking change made to use darwin-rebuild instead of calling the activation scripts directly. Unfortunately this change meant it was no longer meant to use nh as a darwin-rebuild replacement, as it would depend on darwin-rebuild itself. So if darwin-rebuild was disabled (e.g. by setting system.tools.enable = false), nh would fail to activate the system with an error like the following:
> Comparing changes
<<< /run/current-system
>>> /var/folders/h7/34fnxyx94lv_hkg1fmg658fr0000gn/T/nh-osusP10v/result
No version or selection state changes.
Closure size: 2055 -> 2055 (0 paths added, 0 paths removed, delta +0, disk usage +0B).
> Activating configuration
env: ‘/var/folders/h7/34fnxyx94lv_hkg1fmg658fr0000gn/T/nh-osusP10v/result/sw/bin/darwin-rebuild’: No such file or directory
This PR simply adds a check whether darwin-rebuild exists, and if not, falls back to the old behavior.
(If it's undesirable for this configuration to be supported then perhaps a warning should be added when activate is used, but I think compatibility should be kept at least for now, because it was done in a minor release, and breaking changes should only happen in major releases according to semver (which is why marked it as a bug fix, since it's fixing a regression from a semver point of view))
Tested in the following cases:
- Ensure it invokes
darwin-rebuildby default - Ensure it falls back to
activateifdarwin-rebuilddoesn't exist - Ensure it also invokes
activate-userif it's the non-deprecated version and it invokedactivate
Sanity Checking
- [x] I have updated the changelog as per my changes
- [x] I have tested, and self-reviewed my code
- Style and consistency
- [ ] I ran
nix fmtto format my Nix code - [x] I ran
cargo fmtto format my Rust code - [ ] I have added appropriate docunentation to new code
- [x] My changes are consistent with the rest of the codebase
- [ ] I ran
- Correctness
- [x] I ran
cargo clippyand fixed any new linter warnings.
- [x] I ran
- 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 - [x]
aarch64-darwin
- [ ]
Add a :+1: reaction to pull requests you find important.
Summary by CodeRabbit
-
Bug Fixes
- macOS activation is more resilient: if the standard rebuild tool isn’t available, activation falls back to direct activation and may perform a user-level activation step.
- Automatically selects appropriate activation method and elevation based on the environment.
- Provides clearer, more specific error messages for activation and user activation failures.
-
Documentation
- Added an Unreleased entry documenting the macOS activation fallback behavior.
Walkthrough
Detects darwin-rebuild presence and new vs legacy activation in src/darwin.rs, conditionally runs either darwin-rebuild activate or out_path/activate, optionally runs activate-user for legacy flow, adjusts elevation logic and error contexts. Updates CHANGELOG.md to document the Darwin fallback. No public API changes.
Changes
| Cohort / File(s) | Summary |
|---|---|
DocumentationCHANGELOG.md |
Added Unreleased -> Fixed entry documenting Darwin-specific fallback: when darwin-rebuild is absent, activation falls back to executing activate (and activate-user when applicable). Documentation-only. |
Darwin activation logicsrc/darwin.rs |
Added detection for darwin-rebuild (has_darwin_rebuild) and activation-style detection (uses_new_activation); select activation command conditionally (darwin-rebuild activate vs out_path/activate); compute should_elevate and apply elevation accordingly; run legacy activate-user when needed; improved error contexts and distinct failure messages. No public signatures changed. |
Sequence Diagram(s)
sequenceDiagram
autonumber
actor User
participant CLI as CLI
participant FS as Filesystem
participant Sudo as Elevation
participant Shell as System Shell
User->>CLI: trigger activation
CLI->>FS: stat `darwin-rebuild`
alt darwin-rebuild exists
CLI->>FS: inspect `activate-user` (detect new activation)
CLI->>CLI: set uses_new_activation, should_elevate
alt should_elevate
CLI->>Sudo: run `darwin-rebuild activate`
Sudo->>Shell: execute activation
else
CLI->>Shell: run `darwin-rebuild activate`
end
else darwin-rebuild missing
CLI->>FS: inspect `out_path/activate` and `activate-user`
CLI->>CLI: set uses_new_activation=false, should_elevate=true
CLI->>Sudo: run `out_path/activate`
Sudo->>Shell: execute activation
opt legacy user activation (not uses_new_activation)
CLI->>Shell: run `out_path/activate-user`
end
end
note over CLI,Shell: Errors include contextual messages for activation vs user activation failures
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45–60 minutes
Pre-merge checks (2 passed, 1 warning)
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title Check | ✅ Passed | The title “darwin: fix activation without darwin-rebuild” accurately and concisely captures the primary change—restoring activation fallback on macOS when the darwin-rebuild tool is unavailable—without extraneous detail, making it clear to reviewers scanning the pull request history. |
[!TIP]
👮 Agentic pre-merge checks are now available in preview!
Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
- Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
- Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.
Please see the documentation for more information.
Example:
reviews: pre_merge_checks: custom_checks: - name: "Undocumented Breaking Changes" mode: "warning" instructions: | Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post.
✨ Finishing Touches
- [ ] 📝 Generate Docstrings
🧪 Generate unit tests
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Comment @coderabbitai help to get the list of available commands and usage tips.
Made the comment shorter so it passes the format CI check. Idk what all this AI stuff is I've never seen it before, not sure what I'm supposed to do with it exactly.
You may disregard the AI comments. I'm currently looking to see if it provides helpful comments that help guide my reviews (as the sole maintainer) or if it creates useless noise. Outlook not so good.
I'll take a review later today. Please feel free to remind me with a ping if I forget. Also CC @khaneliman as someone more aware of nix-darwin's internals.
I mean, it was a deliberate choice https://github.com/nix-community/nh/pull/238#discussion_r2003366687
I see. So should I add a warning about it and mark that it will be removed in the future? (v5.0.0)