fix: declutter writable activation artifacts before nix linkGeneration - #2323
Conversation
Hermes activate.sh replaces Nix-managed systemd unit symlinks with writable copies so Hermes can auto-refresh them. Cass hydrate.sh writes sources.toml. Both happen after writeBoundary, so they block the next nix-switch which expects only symlinks in those locations. Add pre-linkGeneration cleanup hooks that remove any non-symlink leftovers before home-manager's linkGeneration phase runs.
|
Warning Indent Zero is shutting down on August 7th. Please migrate over to Indent 2.0 to continue getting PR reviews.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Disabled knowledge base sources:
📝 WalkthroughSummary by CodeRabbit
WalkthroughHome Manager now cleans stale Cass and Hermes activation artifacts before ChangesActivation cleanup
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| lib.mkIf host.isKyber { | ||
| # Clean up writable copies that Hermes activate.sh creates (replacing Nix-managed | ||
| # symlinks) so they don't block the next nix-switch's linkGeneration. | ||
| home.activation.hermesCleanup = config.lib.dag.entryBefore [ "linkGeneration" ] '' |
There was a problem hiding this comment.
Cleanup can be scheduled before writeBoundary/checkLinkTargets.
lib.hm.dag.entryBefore x is defined as entryBetween x [ ] (see modules/lib/dag.nix), so there is no constraint tying this entry to run after writeBoundary. Home-manager's own convention (home.activation docs) is: "If the script block produces any observable side effect … it must be placed after the special writeBoundary script block."
Why this matters here: checkLinkTargets runs entryBefore [ "writeBoundary" ] and only tolerates an existing non-symlink at a target path when cmp -s finds the content identical to the store version. activate.sh currently writes back the byte-identical content via printf '%s\n' "$content", so checkLinkTargets happens to pass today. The first time any of the three hermes units gets a Nix-side change (Environment=, ExecStart=, etc.), the writable copy on disk will differ from the new store version, checkLinkTargets will abort activation — and if the DAG has scheduled this cleanup after checkLinkTargets, the cleanup never runs and the switch is blocked exactly as this PR is trying to prevent.
Suggested fix (also applies to cassSourcesCleanup):
home.activation.hermesCleanup = config.lib.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
...
'';| home.activation.hermesCleanup = config.lib.dag.entryBefore [ "linkGeneration" ] '' | |
| home.activation.hermesCleanup = config.lib.dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] '' |
| # block the next nix-switch. | ||
| home.activation.cassSourcesCleanup = config.lib.dag.entryBefore [ "linkGeneration" ] '' | ||
| $DRY_RUN_CMD ${pkgs.bash}/bin/bash -c ' | ||
| if [ -f "${config.home.homeDirectory}/.config/cass/sources.toml" ]; then |
There was a problem hiding this comment.
Darwin path missed. hydrate.sh:37-41 selects ~/Library/Application Support/cass/sources.toml on Darwin and ~/.config/cass/sources.toml elsewhere, and this module is imported unconditionally (home-manager/programs/default.nix:11). The cleanup hard-codes the Linux path, so on macOS it never fires. Today this is defensive-only (sources.toml isn't declared in home.file anywhere I could find), but it does mean the migration case the hydrate.sh comment calls out ("Older generations symlinked this file into the Nix store; replace it.") is only handled on Linux.
Consider selecting the path from Nix, e.g.:
let
sourcesFile =
if pkgs.stdenv.isDarwin then
"${config.home.homeDirectory}/Library/Application Support/cass/sources.toml"
else
"${config.home.homeDirectory}/.config/cass/sources.toml";
in
What
Two pre-
linkGenerationhome-manager activation hooks that remove writable files left by Hermesactivate.shand Casshydrate.shbefore the next switch expects clean symlinks.Why
activate.shreplaces Nix-managed systemd unit symlinks with writable copies so Hermes can auto-refresh themhydrate.shwritessources.tomlto~/.config/cass/writeBoundary, so on the nextnix-switch, home-manager'slinkGenerationfinds regular files instead of symlinks and refuses to clobber themFiles changed
home-manager/services/hermes/default.nix— cleanup beforelinkGenerationforhermes-gateway.service,hermes-dashboard.service,hermes-dashboard-proxy.servicehome-manager/programs/cass/default.nix— cleanup beforelinkGenerationforsources.tomlSummary by cubic
Clean up writable activation artifacts before
home-managerlinkGenerationso the nextnix-switchcan safely recreate symlinks and avoid clobber errors. Adds pre-linkGenerationhooks for Hermes and Cass.linkGeneration(hermes-gateway.service,hermes-dashboard.service,hermes-dashboard-proxy.service).~/.config/cass/sources.tomlbeforelinkGeneration.Written for commit b3ce01f. Summary will update on new commits.