Files
Nomarchy/.gitea/workflows/check.yml
Bernardo Magri 2dda8e2bb5
Some checks failed
Check / eval-and-lint (push) Failing after 3h0m3s
ci: check flake outputs per-output to skip the OOM-heavy package
`nix flake check --no-build` also evaluates packages.allThemeVariants, a
linkFarm whose drvPath forces all 22 home generations into memory at once
— the runner OOM-killed there ("Killed" after allThemeVariants). Replace
it with an explicit per-output eval that forces all 4 system closures
(incl. assertions), both standalone home generations, the installer VM
package, the overlay and the app, and skips only allThemeVariants/default.
Each tryEval is GC'd before the next, so peak memory is one config rather
than twenty-two. The eval matrix already validates every palette
one-at-a-time, so dropping that package from CI loses no real coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 22:51:05 +01:00

191 lines
10 KiB
YAML

# Nomarchy CI — eval + lint.
#
# Catches the regressions that hurt today:
# 1. Flake stops evaluating (broken option ref, missing import, etc.).
# Checked per-output rather than via `nix flake check` so we can skip
# packages.allThemeVariants — the 22-generation linkFarm that OOMs the
# runner; every palette is validated one-at-a-time by the matrix (4).
# 2. A `nomarchy-*` shell script has a syntax error or a shellcheck
# error-severity issue.
# 3. `docs/SCRIPTS.md` drifts from the repo state because somebody
# added / removed / renamed a script and didn't run the generator
# (the pre-commit hook handles this, but only when enabled per-clone).
# 4. An opt-in nomarchy.* toggle stops evaluating. `nix flake check`
# only evaluates the four default configs, so a bug that only fires
# when a toggle is flipped sails through (e.g. the impermanence
# systemd-stage-1 assertion). nomarchy-eval-matrix layers each toggle
# onto the default config and forces system.build.toplevel.
#
# Doesn't build ISOs — that needs a binary cache. Add a separate job
# once Cachix/Attic is in place.
name: Check
on:
push:
branches: [main]
pull_request:
jobs:
eval-and-lint:
runs-on: ubuntu-latest
# Flakes for every `nix` invocation in the job (the bare `nix flake
# check` below relies on this; the scripts pass the flag themselves).
# sandbox=false because Stylix/base16.nix do import-from-derivation —
# eval realizes fetched `-source` paths mid-check, and the single-user
# Nix in this container can't set up the build sandbox (no user
# namespaces), which otherwise surfaces as "path '…-source' is not
# valid". NIX_SSL_CERT_FILE because we add nix to PATH without sourcing
# the installer's profile (which is what normally exports it).
env:
NIX_CONFIG: |
experimental-features = nix-command flakes
sandbox = false
NIX_SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Nix
# Plain shell install rather than a JS action: act_runner's bundled
# `act` only supports up to node20, and nix-installer-action@main
# moved to node24 ("runs.using ... got node24"). A run step has no
# node-runtime coupling. Single-user (--no-daemon) needs no systemd,
# which the catthehacker container doesn't run as PID 1.
#
# The installer runs as root here and honours build-users-group=
# nixbld from its bundled nix.conf, aborting unless that group exists
# AND has members. Create the nixbld group + build users (what a
# multi-user install does) before running it.
#
# Pin the Nix version: the latest (2.34) uses lazy-trees / a git
# cache that doesn't materialise flake-input `-source` paths into
# the store, so Stylix's import-from-derivation reads fail with
# "path '…-source' is not valid". 2.31.5 matches the Nix that wrote
# flake.lock locally and evaluates the flake cleanly.
run: |
NIX_VERSION=2.31.5
groupadd -r nixbld 2>/dev/null || true
for i in $(seq 1 10); do
useradd -r -g nixbld -G nixbld -d /var/empty \
-s /usr/sbin/nologin -c "Nix build user $i" "nixbld$i" 2>/dev/null || true
done
curl -L "https://releases.nixos.org/nix/nix-${NIX_VERSION}/install" | sh -s -- --no-daemon
echo "$HOME/.nix-profile/bin" >> "$GITHUB_PATH"
- name: Materialize flake-input sources for eval
# Walker's flake reads its own source tree during evaluation:
# importTOML resources/config.toml in its home-manager module and
# lib.fileset.toSource for the package src (cargoLock.lockFile =
# "${src}/Cargo.lock"). On a cold store the input source isn't
# materialised, so flake check / eval die with "path '…-source' is
# not valid" (works locally only because prior builds materialised
# it; `nix flake archive` reports the input but doesn't make the
# fileset-derived src readable). `nix build` of walker's src
# eagerly realises it — and the input it reads from — priming the
# store so the later eval steps find every path valid.
run: |
nix build --no-link --impure --expr 'let f = builtins.getFlake (toString ./.); in f.inputs.walker.packages.${builtins.currentSystem}.default.src'
- name: Check flake outputs (except the 22-variant pre-cache package)
# Stand-in for `nix flake check --no-build`. That also evaluates
# packages.allThemeVariants — a linkFarm whose drvPath forces all 22
# home generations into memory at once, OOM-killing the runner. The
# eval matrix below already validates every palette one-at-a-time, so
# that package's CI value is near-zero. Here we force every other
# output (all 4 system closures incl. assertions, both standalone
# home generations, the installer VM package, the overlay, the app)
# and skip only allThemeVariants/default. Each tryEval is GC'd before
# the next, so peak memory is one config, not twenty-two.
run: |
nix eval --impure --raw --expr 'let
f = builtins.getFlake (toString ./.);
lib = f.inputs.nixpkgs.lib;
sys = "x86_64-linux";
ok = x: (builtins.tryEval (builtins.seq x true)).success;
checks = {
"nixos.default" = ok f.nixosConfigurations.default.config.system.build.toplevel.drvPath;
"nixos.nomarchy-installer" = ok f.nixosConfigurations.nomarchy-installer.config.system.build.toplevel.drvPath;
"nixos.installerVm" = ok f.nixosConfigurations.installerVm.config.system.build.toplevel.drvPath;
"nixos.nomarchy-live" = ok f.nixosConfigurations.nomarchy-live.config.system.build.toplevel.drvPath;
"home.nomarchy" = ok f.homeConfigurations.nomarchy.activationPackage.drvPath;
"home.nixos" = ok f.homeConfigurations.nixos.activationPackage.drvPath;
"packages.installerVm" = ok f.packages.${sys}.installerVm.drvPath;
"overlays.default" = ok (builtins.isFunction f.overlays.default);
"apps.installerVm" = ok f.apps.${sys}.installerVm.program;
};
failed = builtins.attrNames (lib.filterAttrs (_: v: !v) checks);
in if failed == [] then "ALL OK"
else throw ("flake-output checks failed: " + builtins.concatStringsSep ", " failed)'
- name: Evaluate opt-in toggle / palette / home matrix
# flake check never flips a nomarchy.* toggle; this does. jq is
# provided via nix shell so the step doesn't depend on the runner
# image preinstalling it.
run: nix shell nixpkgs#jq --command ./bin/utils/nomarchy-eval-matrix
- name: Lint nomarchy-* scripts (bash -n + shellcheck)
run: |
# Mirror what .githooks/pre-commit runs locally, but across the
# whole tree instead of just changed files. Pre-commit gates
# individual commits; CI gates branches (including --no-verify
# bypasses).
set -e
fail=0
while IFS= read -r script; do
[[ -f "$script" ]] || continue
# Python helpers ship under the same nomarchy- prefix
# (e.g. nomarchy-haptic-touchpad). Skip non-bash.
head -1 "$script" | grep -qE '^#!.*\bbash\b' || continue
if ! bash -n "$script"; then
echo "::error file=$script::bash syntax error"
fail=1
fi
if ! nix shell nixpkgs#shellcheck --command shellcheck \
--severity=error --shell=bash "$script"; then
echo "::error file=$script::shellcheck error-severity issue"
fail=1
fi
done < <(find features/scripts/utils core/system/scripts \
themes/engine/scripts \
-maxdepth 1 -type f -name 'nomarchy-*')
exit "$fail"
- name: docs/SCRIPTS.md is up to date
run: |
# Regenerate to a temp file and compare. If different, the
# contributor forgot to run the generator (or skipped the
# pre-commit hook). Fail loudly and tell them the fix.
./bin/utils/nomarchy-docs-scripts --out /tmp/SCRIPTS.regen.md
if ! diff -q docs/SCRIPTS.md /tmp/SCRIPTS.regen.md >/dev/null; then
echo "::error::docs/SCRIPTS.md is stale."
echo "Run: ./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md"
echo "Then commit the regenerated file."
echo "--- diff ---"
diff -u docs/SCRIPTS.md /tmp/SCRIPTS.regen.md || true
exit 1
fi
- name: installer/hardware-db.sh references real nixos-hardware modules
run: |
# Every 4th-pipe-field in HARDWARE_DB is a nixos-hardware module
# name. Half the DB used to point at modules that don't exist
# (e.g. microsoft-surface-pro-8 — there's only -pro-intel and
# -pro-9), which made the install fail at eval time with
# cryptic "attribute not found" errors on real laptops. This
# step catches that regression class.
awk -F'|' '/^ "/ { gsub(/"/,"",$4); gsub(/^[[:space:]]+|[[:space:]]+$/,"",$4); if ($4) print $4 }' \
installer/hardware-db.sh | sort -u > /tmp/db-refs.txt
nix eval --impure --json --expr '
let
nh = (builtins.getFlake (toString ./.)).inputs.nixos-hardware.nixosModules;
in builtins.attrNames nh' \
| nix shell nixpkgs#jq --command jq -r '.[]' | sort -u > /tmp/db-real.txt
missing=$(comm -23 /tmp/db-refs.txt /tmp/db-real.txt)
if [[ -n "$missing" ]]; then
echo "::error::hardware-db.sh references nixos-hardware modules that don't exist:"
printf ' - %s\n' $missing
echo "Either fix the name (check the actual attr in nixos-hardware) or drop the row."
exit 1
fi