| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
| |
The zfs green run OOM-killed cc1plus three times during AUR C++ builds:
makepkg runs -j$VM_CPUS (4), and parallel compiles at ~700 MB each overran
the 4 GiB default. The install still passed (yay retries), but the kills
showed up as attributed issues. 8 GiB gives the four jobs headroom.
Overridable via VM_RAM as before.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
init_vm_paths suffixed the disk image per profile but shared one
OVMF_VARS.fd across btrfs and zfs. NVRAM holds the UEFI boot entries and
lives outside the qcow2, so a disk-snapshot revert can't restore it. A zfs
run's ZFSBootMenu entries clobbered the btrfs GRUB entry, and with no
removable ESP fallback the btrfs base then booted to "no bootable device"
and timed out before archsetup ran.
NVRAM now carries the same per-profile suffix as the disk image, so the two
profiles keep separate boot state. Validated by a full green zfs run
(ArchSetup exit 0, Testinfra 96 passed / 0 failed).
|
| |
|
|
|
|
| |
Both runners now validate through run_testinfra_validation, so the shell sweep validation.sh ran is dead. Delete run_all_validations, validate_all_services, run_full_validation, the ~35 validate_* checks, and validation_pass/fail/warn/skip (called only by those checks). Keep the live helpers the runners and testinfra.sh still use: ssh_cmd, attribute_issue, capture_pre/post_install_state, analyze_log_diff, categorize_errors, generate_issue_report, and the VALIDATION_* counters plus issue arrays. The file drops from 1156 lines to 314.
Closes the P5 follow-up from the Testinfra cutover.
|
| |
|
|
| |
run-test-baremetal.sh runs under set -e, and the P-D migration left run_testinfra_validation called bare. It returns pytest's rc, so a failing sweep aborted the script before it wrote the report or the TEST FAILED summary. The old run_all_validations returned 0 and never tripped set -e. Mirror the VM runner: set +e around the call, capture the rc, and derive TEST_PASSED from it so the report and summary always run.
|
| |
|
|
|
|
|
|
|
|
| |
run-test-baremetal.sh SSHed to the target as root by password throughout, which archsetup's sshd hardening (PermitRootLogin prohibit-password) kills mid-install, the same break the VM runner already fixed. It also still called the validation.sh shell sweep (run_all_validations, validate_all_services, validate_zfs_services), the last caller keeping those functions alive.
It now mirrors the VM runner. After the first SSH, and after any genesis rollback so the key survives it, inject_root_key authorizes a throwaway root key, and every later ssh_cmd plus the raw scp transfers and log-copies thread SSH_KEY_OPT to survive the hardening. The shell sweep is replaced with run_testinfra_validation, now the authoritative validator on both runners. A --port option, threaded through every SSH and scp, lets the runner target a test VM on 2222 instead of only real hardware on 22.
inject_root_key now authorizes root@$VM_IP instead of root@localhost, so one helper serves both runners (the VM runner sets VM_IP=localhost).
Validated against the ZFS VM (--validate-only, localhost:2222): connectivity, the ZFS check, key authorization, and the Testinfra sweep all connect and run over the key-based ssh-config. A green bare-metal install still needs real ZFS hardware.
|
| |
|
|
|
|
| |
The Testinfra boot and backup checks asserted btrfs behavior unconditionally, so they failed on a ZFS root once the ZFS VM path started running them. ZFS boots via ZFSBootMenu, not GRUB. archsetup skips the systemd-hook switch and the mkinitcpio rebuild on ZFS, and on a ZFS+virtio VM it never edits mkinitcpio.conf at all. Branch each check on the existing zfs_root/has_nvme fixtures: assert the ZFSBootMenu EFI binary on ZFS (GRUB on btrfs), gate the mkinitcpio.conf backup on archsetup actually editing the file, and check the console font in /etc/vconsole.conf on ZFS (the initramfs on non-ZFS).
Surfaced by the first full ZFS VM run, which completed archsetup cleanly (exit 0). These were the only 3 failures.
|
| |
|
|
|
|
|
|
|
|
| |
The VM harness only built one btrfs base image, so every ZFS-conditional check in the Testinfra suite skipped and the ZFS install path went untested in automation. I added an FS_PROFILE selector (btrfs default, zfs) so `make test FS_PROFILE=zfs` can target a ZFS root.
init_vm_paths derives the image name from FS_PROFILE and validates it. btrfs keeps the legacy unsuffixed archsetup-base.qcow2 so existing images and invocations are untouched. The zfs profile gets archsetup-base-zfs.qcow2. create-base-vm.sh picks archsetup-test.conf vs the new archsetup-test-zfs.conf (FILESYSTEM=zfs, NO_ENCRYPT=yes for an unattended install), and the Makefile resolves the matching image for its base-VM check.
The archsetup run config stays shared. archsetup reads no filesystem key. It detects ZFS from the live root via is_zfs_root, so the ZFS branch fires on its own once the base image is ZFS. The design doc is reconciled to that: no separate archsetup-vm-zfs.conf, and the non-ZFS profile is btrfs, not ext4.
Building the ZFS base image and running the ZFS sweep green is next.
|
| |
|
|
|
|
|
|
| |
A full archsetup install with heavy AUR builds (vagrant and its git-cloned
installers) can run past the old 90-minute monitor cap on a slow mirror. When
that happened the run stopped monitoring mid-install and validated a
half-installed system, producing spurious late-step failures. Raise MAX_POLLS
from 180 to 300 (90 -> 150 minutes) so a slow-but-healthy install completes.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
run-test.sh no longer runs the shell run_all_validations sweep; the Testinfra
pytest sweep now drives the run's pass/fail. run_testinfra_validation returns
pytest's exit code (and treats "could not run" as a failure, not a silent
pass), surfaces the pass/skip/fail counts through the shared VALIDATION_*
counters, and parses the attribution file so generate_issue_report still
buckets failures into archsetup / base_install / unknown.
The shell-sweep functions stay in validation.sh for now because
run-test-baremetal.sh still calls them; removing them (after migrating the
bare-metal runner) is filed as a follow-up.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add post-install checks beyond the original shell sweep, validated against a
live VM: test_hardening (sshd prohibit-password, quiet-printk sysctl, emptied
/etc/issue, console font, EFI mount perms), test_config_applied (pacman
ParallelDownloads/Color/multilib, makepkg flags, NetworkManager drop-ins,
fail2ban jail, reflector), and test_backups (the .archsetup.bak files
backup_system_file leaves behind — end-to-end proof of that feature).
The new tests caught a real bug: ParallelDownloads stayed at Arch's default 5
because the sed only matched a commented "#ParallelDownloads", but current Arch
ships it uncommented. Match both (^#?ParallelDownloads) so the intended 10 takes
effect.
Verified against a kept VM: 95 passed, 10 skipped (the one remaining failure was
the pre-fix ParallelDownloads on the already-built VM, which the sed fix
resolves on the next fresh install).
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
VM run #2 exposed two test bugs (archsetup itself passed clean, 53/0/0):
- ScopeMismatch errors on 26 tests: the host-dependent fixtures were
session-scoped, but Testinfra's host fixture is module-scoped, and a
session fixture cannot request a module one. Drop those fixtures to
module scope.
- test_console_font_in_initramfs hardcoded /boot/initramfs-linux.img; this
fleet runs linux-lts, so the image is initramfs-linux-lts.img. Pick the
main (non-fallback) initramfs by glob instead.
|
| |
|
|
|
|
| |
The VM test SSHes into the guest as root with a password for the whole run. archsetup hardens sshd to PermitRootLogin prohibit-password and reloads it partway through the install, so every SSH after that step failed with "Permission denied" and the run aborted before any validation — make test had been silently broken since the hardening landed.
inject_root_key authorizes a throwaway root key right after the first SSH (before archsetup runs) and the ssh/scp helpers now add -i <key> via SSH_KEY_OPT. prohibit-password still allows root key auth, so the harness survives the very hardening it validates. Password stays as the fallback, so the change is additive.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Port all ~26 post-install checks from validation.sh to pytest/Testinfra,
reaching parity before the cutover. Adds test_users, test_packages,
test_services, test_desktop, test_boot, test_keyring, and test_archsetup
(88 tests after parametrizing groups, services, timers, tools, and configs),
plus shared conftest fixtures for ZFS/NVMe/compositor/networking gating.
The shell sweep's three outcomes map cleanly: hard failures become assertions,
advisory warnings and unmet preconditions (headless compositor, slirp
networking, optional services, non-ZFS/non-NVMe hosts) become skips.
One correctness fix vs the shell sweep: check awww, not swww — archsetup
installs awww (swww's successor) and `pacman -Q swww` no longer matches.
Verified on the host: py_compile clean, pytest --collect-only green (88 tests).
The sweep against a real VM is verified by the make test run that follows.
|
| |
|
|
|
|
|
|
| |
Stand up the Testinfra/pytest harness alongside the existing shell sweep so the two can be compared for parity before pytest takes over.
Adds scripts/testing/tests/ (conftest with failure attribution markers, a report hook, and a target_user fixture, plus three parity checks: user, ufw, dotfiles) and scripts/testing/lib/testinfra.sh, which injects a throwaway SSH key into the VM and runs pytest over SSH. The sweep is advisory here (RUN_TESTINFRA toggle, non-fatal) and does not yet affect pass/fail. Pulls python-pytest and python-pytest-testinfra into make deps.
Verified on the host: py_compile clean, pytest --collect-only green, bash -n and shellcheck clean. The sweep running against a real VM is verified by the next make test run.
|
| |
|
|
|
|
|
|
| |
Three release cleanups, all behavior-preserving for my machines:
- Gated the Logitech BRIO udev rule behind INSTALL_DEVICE_UDEV_RULES (default yes, opt-out), so the device-specific rule is off for anyone without that hardware. Added the config read, validation, and a conf.example entry.
- Added a GPL-3.0-or-later SPDX-License-Identifier header after the shebang of all 24 shell scripts in the repo.
- Standardized boolean conditionals on the explicit [ "$var" = "true" ] form, replacing the bare `if $var` idiom. The STEPS function-dispatch is left alone, since it runs a function name rather than testing a boolean.
|
| |
|
|
| |
The check captured 'ls path && echo yes', so a present linger file produced 'path\nyes', which never string-equals yes — every run warned regardless of actual state. Forensics on a kept VM showed lingering correctly enabled all along (file present mid-install, loginctl Linger=yes, logind healthy): the original VM-artifact hypothesis was wrong, archsetup's enable-linger calls were always fine. test -e captures cleanly; verified returning 'yes' against the live VM.
|
| |
|
|
| |
The 19:06 verification run showed the portal skip not firing: a socket-activated xdg-desktop-portal process exists even headless, so the process check was the wrong precondition. The skip now keys on a running Hyprland, same as the socket check. That run confirmed the other three skips live (warnings 5 to 2); the remaining counted warnings are this portal case and the lingering question, which stays open.
|
| |
|
|
| |
Four warnings fired on every headless VM run, training the reader to ignore the warning count: the Hyprland socket and portal queries (no graphical login), the mDNS ping (slirp passes no multicast), and docker-not-responding (enabled but deliberately not started pre-reboot). Each now detects its precondition and logs a skip that counts nowhere; the warn paths stay for the cases that are real (compositor running without a socket, portal running but unqueryable, mDNS failing on real networking, docker active but dead). The lingering warning stays — it needs its own investigation.
|
| |
|
|
| |
The dotfiles validation hardcoded .dotfiles/common/.zshrc, but a none install stows the standalone minimal/ tree, so the first none-run ever to reach validation failed on a correct symlink. The expected path now follows DESKTOP_ENV from the VM conf.
|
| | |
|
| |
|
|
| |
The dotfiles live in a separate repo now, so the VM test clones that source, bundles it, and clones from the bundle into /tmp/dotfiles-test on the VM. archsetup's in-VM clone of DOTFILES_REPO then resolves against the local path with no network. DOTFILES_SOURCE overrides the source for testing a local checkout instead of the published repo. The cleanup trap tracks the host-side bundle and clone, so a mid-run abort leaves nothing behind.
|
| |
|
|
|
|
| |
init runs under #!/bin/sh but used $(<file) to read /etc/hostname, a bashism that breaks on a strict POSIX sh. I switched it to $(cat) and quoted $interface_up in the same script.
The two VM_IP assignments in the test scripts are read by the sourced validation.sh, which shellcheck can't follow, so they now carry a documented disable=SC2034 instead of a bare suppression. The rest of the shellcheck findings across the scripts are intentional (word-splitting on $SSH_OPTS, integer tests in [ ]) or already accepted, so I left them alone.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two real bugs and a sweep of hygiene across the harness. `make test`
passed cleanly on this branch with the same 52/0/5 profile as the
2026-05-11 run, so the wiring is verified end-to-end.
Real bugs:
- `lib/vm-utils.sh` `snapshot_exists` was running
`qemu-img snapshot -l | grep -q "$snapshot_name"`, which matches the
name as a substring anywhere in the output — including inside dates
or filenames in other fields. Replaced with an awk field extraction
on the TAG column plus `grep -Fxq` for a whole-line literal match.
- `run-test-baremetal.sh` was setting `VALIDATION_PASSED=true|false`
after validation, but `validation.sh` already uses
`VALIDATION_PASSED` as a pass counter. The test report then
referenced `$VALIDATION_PASSED_COUNT`, which is defined nowhere.
Renamed the boolean to `TEST_PASSED` (matching run-test.sh's
pattern) and report the actual counter.
Cleanup traps and arg validation:
- `run-test.sh` now installs a top-level EXIT trap that, on abort,
kills QEMU and restores the clean-install snapshot. A
`CLEANUP_DONE=1` sentinel keeps the existing normal-path cleanup
from double-firing. This is the recurring pain from 2026-05-11
where two failed runs left orphaned QEMU processes and dirty base
disks behind.
- `create-base-vm.sh` and `debug-vm.sh` got the same kind of trap, plus
`debug-vm.sh` now rejects non-`.qcow2` paths up front instead of
letting QEMU fail later.
- `run-test.sh`, `run-test-baremetal.sh`, and `cleanup-tests.sh` now
validate that options with required values actually receive one
(`${var:?msg}` for `--script`/`--snapshot`/`--host`/`--password`,
numeric check for `--keep`).
- `run-test-baremetal.sh` traps the temp git bundle for cleanup if the
script aborts before its explicit `rm`. The ZFS rollback loop now
uses `while IFS= read -r ds` and quotes `$ds` inside the ssh_cmd so
dataset names with whitespace wouldn't break it.
Smaller hygiene:
- `vm-utils.sh` `check_ovmf` also checks `OVMF_VARS_TEMPLATE`; `start_qemu`
validates disk and ISO paths before building the QEMU command;
numeric tests quoted.
- `cleanup-tests.sh` find expression for temp disks wrapped in
`\( ... -o ... \)`, all `while read` loops use `IFS= read -r`,
orphaned QEMU cleanup tries SIGTERM with a 2s sleep before SIGKILL.
- `create-base-vm.sh` moved the "Copy an archangel-*.iso" info line
before its `fatal` instead of after (unreachable), and added the
serial-log path to the final summary.
- `lib/logging.sh` `stop_timer` no longer produces `$((end - ))` when
the named timer was never started.
- `lib/network-diagnostics.sh` `read` → `IFS= read -r`.
- `setup-testing-env.sh` now installs all missing pacman packages in
one transaction instead of one-at-a-time (avoids half-installed
state if package N fails). KVM check also verifies the user has
read+write on `/dev/kvm` and prints the `gpasswd -a $(id -un) kvm`
fix if not.
A few items from the review I deliberately skipped: replacing the
codebase-wide unquoted `$SSH_OPTS` string with an array (cosmetic, would
need to be done everywhere at once), `set -e` adds where the existing
fall-through-on-failure is intentional, and a `--force` gate on
`create-base-vm.sh` (would break the expected workflow).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Audit pass: each of these had no references anywhere in the repo
(excluding self-references and review notes).
- wip-bootcandy.sh — "wip" prefix, non-executable. Comments mention a
boot animation but the script only installs ly and disables
getty@tty2.
- protonmail-bridge.sh — `pacman_install protonmail-bridge` (the package
landed in extra) plus cmail-setup-finish.sh now cover this.
- wireguard-proton.sh — hardcoded USGA tunnel and a relative
`../assets/wireguard-config/*.conf` path that depends on the caller's
pwd.
- create-archiso-zfs.sh — one-off ISO build snippet, non-executable.
- scripts/testing/lib/finalize-base-vm.sh — libvirt-era leftover. The
test stack moved to direct QEMU and nothing sources or calls it.
|
| |
|
|
|
|
| |
validate_hyprland_plugins and validate_hyprpm_hook checked for the hyprland-plugins-setup script and the hyprpm pacman hook, both removed in 4a3056a (Hyprland 0.54 brings the layouts into core). I deleted the two functions and their calls in validate_window_manager.
I also disabled errexit in run-test.sh from the validation phase onward, so one failed check is counted in VALIDATION_FAILED instead of aborting the run before the report or VM cleanup. About 16 validations across the file do a bare `return 1` after `validation_fail`; any of them firing under the previous behavior would have killed the harness mid-run.
|
| |
|
|
|
|
|
| |
Add rustup toolchain manager to developer_workstation (before AUR
packages that need rust to compile). Add log-cleanup cron job with
test validation. Update ISO glob for archangel naming. Add dunst
icon theme, hyprlock animations, waybar log filtering.
|
| |
|
|
|
| |
Add texlive-latexextra for pdflatex resume builds (enumitem package).
Update test VM password and Arch mirror URL. Process inbox items.
|
| |
|
|
|
|
|
|
| |
hyprpm requires running Hyprland to determine version for plugin
compilation. Move plugin installation from archsetup to a first-login
script (hyprland-plugins-setup) that runs via exec-once. Script checks
if plugins are already installed and skips if so. Update validation to
check for setup script presence instead of enabled plugins.
|
| |
|
|
|
|
|
| |
- Add pacman hook to rebuild hyprpm plugins after Hyprland updates
- Change startup to hyprpm update -n (rebuilds if needed)
- Fix stash-restore to preserve master window using batch commands
- Add validation tests for plugins and hyprpm hook
|
| |
|
|
|
|
| |
Validates that portals.conf uses gtk backend for Settings portal
and that the portal returns color-scheme=1 (prefer-dark) for
libadwaita apps like Nautilus.
|
| |
|
|
|
|
|
|
| |
Set ARCHSETUP_REPO=/tmp/archsetup-test in VM config so archsetup
uses the bundled test repo instead of cloning from remote server.
This ensures tests use the current local changes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
| |
The git bundle command was running from current directory
instead of PROJECT_ROOT, causing it to bundle from wrong repo.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Test Infrastructure:
- Add make test-keep target to keep VM running after test
- Add make test-vm-base target for creating base VM only
- Update make test to auto-create VM if missing
- Remove manual user creation from create-base-vm.sh (archsetup handles it)
- Remove unused USERNAME/USER_PASSWORD from archsetup-test.conf
Archsetup:
- Add snapper-gui-git for btrfs snapshot GUI
- Add SYNC_ACL=yes for snapper permissions
- Add setfacl for wheel group access to /.snapshots
Hyprland:
- Remove easyeffects scratchpad (keep auto-launch)
- Remove ecosystem permissions (caused too many popups)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
| |
|
|
|
| |
Add 'make test' Makefile target to run full VM integration test suite.
Print test report to terminal after generation for immediate visibility.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Replace the never-fully-operational libvirt-based VM test infrastructure
with direct QEMU management and archangel ISO for fully automated,
unattended base VM creation.
Key changes:
- vm-utils.sh: complete rewrite — QEMU process mgmt via PID file,
monitor socket for graceful shutdown, qemu-img snapshots, SSH
port forwarding (localhost:2222)
- create-base-vm.sh: boots archangel ISO, SSHs in, runs unattended
install via config file, verifies, creates clean-install snapshot
- run-test.sh: snapshot revert, git bundle transfer, detached archsetup
execution with setsid, polling, validation, and report generation
- debug-vm.sh: CoW overlay disk, GTK display, auto-cleanup on close
- setup-testing-env.sh: reduced deps to qemu-full/sshpass/edk2-ovmf/socat
- cleanup-tests.sh: PID-based process management, orphan detection
- validation.sh: port-based SSH (backward compatible), fuzzel/foot for
Hyprland, corrected package list paths
- network-diagnostics.sh: getent/curl instead of nslookup/ping (SLIRP)
New files:
- archsetup-test.conf: archangel config for base VM (btrfs, no encrypt)
- archsetup-vm.conf: archsetup config for unattended test execution
- assets/archangel.conf.example: reference archangel config
Deleted:
- finalize-base-vm.sh: merged into create-base-vm.sh
- archinstall-config.json: replaced by archangel .conf format
Tested: full end-to-end run — 51 validations passed, 0 failures.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Rename dotfiles/system to dotfiles/common for clarity - indicates
shared dotfiles used across all desktop environments (DWM, Hyprland).
Removed config directories for uninstalled applications:
- ghostty (using different terminal)
- lf (using ranger instead)
- mopidy (using mpd instead)
- nitrogen (X11-only, obsolete for Wayland)
- pychess (not installed)
- JetBrains (not installed via archsetup)
- youtube-dl (using yt-dlp with different config location)
Kept audacious config for potential future use.
Updated all references in archsetup, CLAUDE.md, todo.org, and
validation.sh.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
|
This flag was removed from archsetup but remained in test scripts.
|