#!/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 = [ { } ]; }).config.system.build.toplevel.drvPath'" exit 1 fi echo "All scenarios evaluated cleanly."