nix flake check --no-build only evaluates the four default configs, so a bug that only fires when a nomarchy.* toggle is flipped sails through — exactly how the vscode option rename and the impermanence systemd-stage-1 assertion both reached main undetected. Add bin/utils/nomarchy-eval-matrix: layers each opt-in scenario (16 toggles, both system and home halves) onto nixosConfigurations.default via extendModules and forces system.build.toplevel.drvPath (which forces assertion checks); also forces all 21 palettes through the system-side Plymouth base00->RGB math that the home-only allThemeVariants never reaches, plus both standalone homeConfigurations. Per-scenario results come from builtins.tryEval so one failure doesn't mask the rest; verified it goes red on a re-injected assertion failure and a bad option ref, green on the current tree. Wired into .forgejo/workflows/check.yml after flake check (jq via nix shell so it doesn't depend on the runner image). AGENT.md §5 now tells future agents to add a scenario when they add/rename an opt-in option. nomarchy-docs-scripts: filter systemd-service declarations (.services. nomarchy-) and denylist the eval-matrix repo tool so neither shows as a dangling "missing" reference; also retroactively clears the latent nomarchy-flathub-init drift from the gaming-flathub commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
120 lines
5.4 KiB
Bash
Executable File
120 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# nomarchy-eval-matrix
|
|
#
|
|
# Evaluates the opt-in nomarchy.* surface that `nix flake check` never
|
|
# touches. flake check only evaluates the four default configs, so a bug
|
|
# that only fires when a toggle is flipped — a renamed option, a failed
|
|
# assertion, a stale reference — sails straight through. Two such bugs
|
|
# shipped to main before this existed (the vscode option rename and the
|
|
# impermanence systemd-stage-1 assertion); both would have been caught
|
|
# here.
|
|
#
|
|
# Each toggle scenario is layered onto nixosConfigurations.default via
|
|
# extendModules and its system.build.toplevel.drvPath is forced (which
|
|
# also forces the assertion checks). Every palette is forced through the
|
|
# system-side Plymouth colour math (which allThemeVariants, being
|
|
# home-only, doesn't exercise). Both standalone homeConfigurations are
|
|
# forced too.
|
|
#
|
|
# Per-scenario results come from builtins.tryEval so one failure doesn't
|
|
# mask the rest — the whole matrix runs, then the script exits non-zero
|
|
# if anything failed.
|
|
#
|
|
# nomarchy-eval-matrix # run the full matrix, table + exit code
|
|
#
|
|
# Add a scenario by editing the `toggleScenarios` attrset in the embedded
|
|
# Nix expression below.
|
|
|
|
set -u
|
|
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
cd "$repo_root"
|
|
|
|
NIX=(nix --extra-experimental-features 'nix-command flakes')
|
|
|
|
read -r -d '' EXPR <<'NIXEOF' || true
|
|
let
|
|
f = builtins.getFlake (toString ./.);
|
|
lib = f.inputs.nixpkgs.lib;
|
|
themeNames = (import ./lib { inherit lib; }).themeNames;
|
|
default = f.nixosConfigurations.default;
|
|
|
|
# Opt-in toggles layered onto the default config. Home-side options go
|
|
# under home-manager.users.nomarchy.nomarchy.*; system-side directly.
|
|
toggleScenarios = {
|
|
"impermanence-single" = { nomarchy.system.impermanence.enable = true; };
|
|
"impermanence-multi" = { nomarchy.system.impermanence = { enable = true; mainLuksName = "crypted_main"; }; };
|
|
"laptop-preset" = { nomarchy.system = { formFactor = "laptop"; laptop.enable = true; }; };
|
|
"desktop-preset" = { nomarchy.system = { formFactor = "desktop"; desktop.enable = true; }; };
|
|
"accessibility-system" = { nomarchy.system.accessibility.enable = true; };
|
|
"gaming-system" = { nomarchy.system.gaming.enable = true; };
|
|
"hybrid-gpu" = { nomarchy.system.features.hybridGPU = true; };
|
|
"hibernation" = { nomarchy.system.hibernation.enable = true; };
|
|
"docker" = { nomarchy.system.virtualization.docker.enable = true; };
|
|
"fwupd" = { nomarchy.hardware.fwupd = true; };
|
|
"accessibility-home" = { home-manager.users.nomarchy.nomarchy.accessibility.enable = true; };
|
|
"gaming-home" = { home-manager.users.nomarchy.nomarchy.gaming.enable = true; };
|
|
"overrides" = { home-manager.users.nomarchy.nomarchy.overrides.enable = true; };
|
|
"panel-bottom" = { home-manager.users.nomarchy.nomarchy.panelPosition = "bottom"; };
|
|
"keymap-variant" = { home-manager.users.nomarchy.nomarchy.keymap = { layout = "de"; variant = "nodeadkeys"; }; };
|
|
"toggles-off" = { home-manager.users.nomarchy.nomarchy.toggles = { waybar = false; idle = false; nightlight = false; }; };
|
|
};
|
|
|
|
forced = x: (builtins.tryEval (builtins.seq x true)).success;
|
|
|
|
tryToplevel = mod:
|
|
forced (default.extendModules { modules = [ mod ]; }).config.system.build.toplevel.drvPath;
|
|
|
|
# Palettes only need the system-side Plymouth path forced — that's the
|
|
# per-palette base00 → RGB float math in themes/engine/plymouth.nix that
|
|
# the home-only allThemeVariants never reaches.
|
|
tryPalette = name:
|
|
forced (default.extendModules { modules = [ { nomarchy.system.theme = name; } ]; }).config.boot.plymouth.themePackages;
|
|
|
|
tryHome = name: forced f.homeConfigurations.${name}.activationPackage.drvPath;
|
|
in {
|
|
toggles = builtins.mapAttrs (_: tryToplevel) toggleScenarios;
|
|
palettes = builtins.listToAttrs (map (n: { name = n; value = tryPalette n; }) themeNames);
|
|
home = builtins.listToAttrs (map (n: { name = n; value = tryHome n; }) [ "nomarchy" "nixos" ]);
|
|
}
|
|
NIXEOF
|
|
|
|
echo "Evaluating opt-in toggle + palette + home matrix (this takes a few minutes)..."
|
|
json="$("${NIX[@]}" eval --impure --json --expr "$EXPR" 2>/tmp/eval-matrix.err)"
|
|
status=$?
|
|
if [[ $status -ne 0 || -z "$json" ]]; then
|
|
echo "ERROR: the matrix evaluation aborted before producing results." >&2
|
|
echo "This usually means an uncatchable error (abort/infinite recursion) in one" >&2
|
|
echo "scenario, or a syntax error in the expression. Full output:" >&2
|
|
cat /tmp/eval-matrix.err >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Render each section and tally failures.
|
|
fails=0
|
|
render() {
|
|
local section="$1"
|
|
echo
|
|
echo "=== $section ==="
|
|
while IFS=$'\t' read -r name ok; do
|
|
if [[ "$ok" == "true" ]]; then
|
|
printf ' ok %s\n' "$name"
|
|
else
|
|
printf ' FAIL %s\n' "$name"
|
|
fails=$((fails + 1))
|
|
fi
|
|
done < <(echo "$json" | jq -r --arg s "$section" '.[$s] | to_entries[] | "\(.key)\t\(.value)"' | sort)
|
|
}
|
|
|
|
render toggles
|
|
render palettes
|
|
render home
|
|
|
|
echo
|
|
if [[ $fails -gt 0 ]]; then
|
|
echo "$fails scenario(s) failed to evaluate. Re-run the failing one directly for the trace, e.g.:"
|
|
echo " nix eval --impure --show-trace --expr 'let f = builtins.getFlake (toString ./.); in (f.nixosConfigurations.default.extendModules { modules = [ { <the toggle> } ]; }).config.system.build.toplevel.drvPath'"
|
|
exit 1
|
|
fi
|
|
echo "All scenarios evaluated cleanly."
|