test(checks): pure-contract guards batch (#49)
All checks were successful
Check / eval (push) Successful in 3m6s
All checks were successful
Check / eval (push) Successful in 3m6s
Four new no-VM checks.* + CI py_compile expansion:
- hardware-db-modules: installer DB module names ∈ pinned
nixos-hardware.nixosModules (a lock bump can rename a module and break
profiled installs on just the matching DMI, invisible to any VM).
- installer-compose-lock: offline lock-composer contract on fixtures.
- installer-disko: pure Nix assert — swapSize "0"/"0G" → no @swap, "2G"
→ sized, withLuks wraps root (permanently guards the #46 install fix).
- windowrule-syntax: builds the generated hyprland.conf and fails on the
pre-0.53 grammar / windowrulev2 keyword (guards ed7fd93).
CI py_compile now covers all tracked *.py; docs/TESTING.md §1 synced.
Implemented by a worktree agent; diff reviewed. Verified V0 (flake check)
+ V1 (each checks.x86_64-linux.* built on main, exit 0); agent's negative
tests confirm each guard fails on a regression.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
86
flake.nix
86
flake.nix
@@ -233,6 +233,92 @@
|
||||
touch $out
|
||||
'';
|
||||
|
||||
# Installer hardware DB ↔ nixos-hardware (item 49): every module
|
||||
# name the DB table and the CPU/GPU/chassis autodetect reference
|
||||
# must exist in the PINNED nixos-hardware.nixosModules — a lock
|
||||
# bump can rename a module upstream (the X1 Carbon → x1-Nth-gen
|
||||
# churn) and break profiled installs on just the matching DMI,
|
||||
# invisible to any VM. The available-set is generated here from
|
||||
# attrNames — the same value fed to nomarchy-install — so it
|
||||
# tracks the lock automatically.
|
||||
hardware-db-modules = pkgs.runCommand "nomarchy-hardware-db-modules"
|
||||
{ nativeBuildInputs = [ pkgs.python3 ]; }
|
||||
''
|
||||
python3 ${./tools/check-hardware-db.py} \
|
||||
${./pkgs/nomarchy-install/hardware-db.sh} \
|
||||
${pkgs.writeText "nixos-hardware-modules.txt"
|
||||
(nixpkgs.lib.concatStringsSep "\n"
|
||||
(builtins.attrNames nixos-hardware.nixosModules))}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
# compose-lock.py offline-composer contract (item 49): the lock
|
||||
# the installer writes on the target with no network must root at
|
||||
# nomarchy, carry every upstream node one level down with its
|
||||
# `follows` paths rebased, and fail closed on a missing narHash or
|
||||
# a pre-existing nomarchy node. Pure — runs the script on fixtures.
|
||||
installer-compose-lock = pkgs.runCommand "nomarchy-installer-compose-lock"
|
||||
{ nativeBuildInputs = [ pkgs.python3 ]; }
|
||||
''
|
||||
python3 ${./tools/check-compose-lock.py} \
|
||||
${./pkgs/nomarchy-install/compose-lock.py}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
# The installer's disko arg contract (item 49): swapSize "0"/"0G"
|
||||
# (bare "0" is what the swap=0 install passes) must yield NO @swap
|
||||
# subvolume, a sized value a correctly-sized one, and withLuks must
|
||||
# gate the LUKS wrapper around the BTRFS root. Pure eval of
|
||||
# disko-config.nix (a plain function) — no disko, no VM.
|
||||
installer-disko =
|
||||
let
|
||||
diskoFor = args: import ./pkgs/nomarchy-install/disko-config.nix
|
||||
({ mainDrive = "/dev/vda"; } // args);
|
||||
rootContent = args:
|
||||
(diskoFor args).disko.devices.disk.main.content.partitions.root.content;
|
||||
btrfsOf = c: if c.type == "luks" then c.content else c;
|
||||
subvols = args: (btrfsOf (rootContent args)).subvolumes;
|
||||
hasSwap = args: builtins.hasAttr "@swap" (subvols args);
|
||||
expect = cond: msg: nixpkgs.lib.assertMsg cond "installer-disko: ${msg}";
|
||||
ok =
|
||||
expect (! hasSwap { swapSize = "0"; })
|
||||
''swapSize "0" produced an @swap subvol''
|
||||
&& expect (! hasSwap { swapSize = "0G"; })
|
||||
''swapSize "0G" produced an @swap subvol''
|
||||
&& expect (hasSwap { swapSize = "2G"; })
|
||||
''swapSize "2G" produced no @swap subvol''
|
||||
&& expect ((subvols { swapSize = "2G"; })."@swap".swap.swapfile.size == "2G")
|
||||
''the @swap swapfile size is not "2G"''
|
||||
&& expect ((rootContent { withLuks = true; }).type == "luks")
|
||||
"withLuks=true did not wrap root in luks"
|
||||
&& expect ((rootContent { withLuks = true; }).name == "crypted")
|
||||
"the luks device is not named 'crypted'"
|
||||
&& expect ((rootContent { withLuks = false; }).type == "btrfs")
|
||||
"withLuks=false did not put btrfs directly on root"
|
||||
&& expect (builtins.hasAttr "@" (subvols { withLuks = false; }))
|
||||
"the no-luks root lost its @ subvolume";
|
||||
in
|
||||
assert ok; pkgs.runCommand "nomarchy-installer-disko" { } "touch $out";
|
||||
|
||||
# Hyprland windowrule dead-syntax guard (item 49): build the
|
||||
# GENERATED hyprland.conf (the ISO's HM output) and fail on a
|
||||
# regression to the pre-0.53 grammar — the `windowrulev2` keyword,
|
||||
# rule-first order (`float, class:^…$`), or a bare `<prop>:`
|
||||
# matcher. That syntax shipped a red config-error banner on every
|
||||
# boot (fixed in ed7fd93); this locks the correct form. Building
|
||||
# one config file is a pure derivation, not a VM.
|
||||
windowrule-syntax =
|
||||
let
|
||||
hyprconf = self.nixosConfigurations.nomarchy-live.config
|
||||
.home-manager.users.${username}.xdg.configFile."hypr/hyprland.conf".source;
|
||||
in
|
||||
pkgs.runCommand "nomarchy-windowrule-syntax"
|
||||
{ nativeBuildInputs = [ pkgs.python3 ]; }
|
||||
''
|
||||
python3 ${./tools/check-windowrule-syntax.py} ${hyprconf}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
# nomarchy-doctor's contract: an induced failed unit flips the
|
||||
# sheet to ✖/exit-1 and names the unit; with the failure
|
||||
# cleared it reports healthy/exit-0. Minimal node (just the
|
||||
|
||||
Reference in New Issue
Block a user