test(state): #133 — pin the #107 legacy-name shim (and its fail-closed gate)
All checks were successful
Check / eval (push) Successful in 4m9s
All checks were successful
Check / eval (push) Successful in 4m9s
mkFlake prefers state.json and still accepts the legacy theme-state.json, because a machine only migrates on its next menu write. Nothing evaluated a checkout carrying ONLY the legacy name, so the shim could rot with every check green — breaking rebuilds for precisely the users who have not opened the menu since #107, i.e. the ones least likely to see it coming. checks.state-legacy-name evaluates two fixtures: legacy-only must resolve, and no-state-at-all must still throw. The gate is half the shim's contract (it turns "no state file" into one readable error instead of a readFile stack from inside the module system) and was equally unpinned. Cheap by construction: mkFlake wraps its return in `builtins.seq _themeState`, so forcing the attrset forces the state read and nothing else — no module system, no home.nix. Hence a one-file fixture and no measurable cost (flake check still ~35s). That file is a SYMLINK to the shipped template's state.json: a copy would drift and the check would quietly start testing a fossil. The fixture also asserts it has no state.json, or it would pass while testing nothing. Both assertions proven by breaking lib.nix — deleting the fallback, then defeating the gate — and watching each fail by name. Delete this check together with the shim and the nomarchy-theme-sync alias. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
45
flake.nix
45
flake.nix
@@ -1511,6 +1511,51 @@
|
||||
in
|
||||
assert ok; pkgs.runCommand "nomarchy-rofi-text-width" { } "touch $out";
|
||||
|
||||
# The #107 rename shipped a compat shim: mkFlake prefers state.json
|
||||
# and still accepts the legacy theme-state.json (lib.nix), because a
|
||||
# machine only migrates on its next menu write. Nothing evaluated a
|
||||
# checkout carrying ONLY the legacy name, so the shim could rot with
|
||||
# every check green — and it is load-bearing for exactly the users who
|
||||
# have not touched the menu since #107, i.e. the ones least likely to
|
||||
# notice before their rebuild breaks.
|
||||
#
|
||||
# Cheap by construction: mkFlake wraps its return in
|
||||
# `builtins.seq _themeState`, so forcing the attrset forces the state
|
||||
# read and nothing else — no module system, no home.nix. Which is also
|
||||
# why the fixture needs only that one file.
|
||||
#
|
||||
# Delete this check together with the shim and the
|
||||
# `nomarchy-theme-sync` alias.
|
||||
state-legacy-name =
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
expect = cond: msg: lib.assertMsg cond "state-legacy-name: ${msg}";
|
||||
legacy = ./checks/fixtures/legacy-state;
|
||||
none = ./checks/fixtures/no-state;
|
||||
evalsOk = src:
|
||||
(builtins.tryEval
|
||||
(builtins.isAttrs (self.lib.mkFlake { inherit src; username = "fixture"; })))
|
||||
.success;
|
||||
ok =
|
||||
# Fixture drift: if someone adds a state.json here the check
|
||||
# would still pass, while testing nothing at all.
|
||||
expect (builtins.pathExists (legacy + "/theme-state.json"))
|
||||
"fixture drift: checks/fixtures/legacy-state has no theme-state.json"
|
||||
&& expect (! builtins.pathExists (legacy + "/state.json"))
|
||||
("fixture drift: checks/fixtures/legacy-state also has a state.json, "
|
||||
+ "so it no longer exercises the legacy-only path")
|
||||
&& expect (evalsOk legacy)
|
||||
("mkFlake cannot evaluate a checkout carrying only theme-state.json — "
|
||||
+ "the #107 compat shim is broken and every pre-#107 machine "
|
||||
+ "fails to rebuild")
|
||||
# The other half of the shim's contract: no state at all must
|
||||
# still fail, and fail here rather than deep in a module.
|
||||
&& expect (! evalsOk none)
|
||||
("mkFlake accepted a checkout with no state file at all — the "
|
||||
+ "fail-closed gate in lib.nix is gone");
|
||||
in
|
||||
assert ok; pkgs.runCommand "nomarchy-state-legacy-name" { } "touch $out";
|
||||
|
||||
# Docking artifact guard: default/no-profile Home Manager output
|
||||
# must still launch both hotplug watchers, put Rofi on the focused
|
||||
# monitor, expose the manual keyboard picker, and never ship the
|
||||
|
||||
Reference in New Issue
Block a user