| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
| |
Live-update guard and the per-profile-NVRAM harness fix close to Resolved.
Filed the archangel btrfs baked-AUR bug (blocks btrfs base on the old ISO,
fixed by the 2026-06-27 ISO) and the guard's live firing test under Manual
testing and validation.
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A pacman -Syu that swaps mesa/hyprland/wayland runtime libs out from under
a running Hyprland session crashes the compositor: the next GPU-lib call
hits a now-"(deleted)" library and SIGABRTs, taking the Wayland clients
with it (hit ratio 2026-06-07, mesa + hyprland upgraded live). It's a
likely driver of ratio's high unsafe-shutdown ratio.
I added a pacman PreTransaction hook (hypr-live-update-guard) on the
GPU/compositor runtime set. When such an upgrade is pending and Hyprland is
running, it aborts before any package is swapped and tells the user to
re-run from a TTY with the session stopped. Aborting at PreTransaction is
safe: nothing is replaced yet, so the live session is untouched. With no
Hyprland running (the from-a-TTY path) the guard stays quiet and the
upgrade proceeds. Override with HYPR_ALLOW_LIVE_UPDATE=1 or by touching the
sentinel file named in the abort message.
archsetup installs the guard and hook in the hyprland path. The decision
logic is covered by tests/hypr-live-update-guard (running/not, override,
multi-package, empty-target). The hook firing against a real pacman
transaction needs a live Hyprland session, filed as a manual test.
|
| | |
|
| |
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
| |
create_user announced "granting permissions" with a bare display call that
never set $action, so a failed sudoers write fell back to error_warn
"$action" and logged the stale "creating user and home directory" from an
earlier step. I set action at that step so a failure names the operation
that actually failed. It was the only stale-$action site in the script (the
rest set action adjacently before their error_warn).
|
| |
|
|
|
|
|
|
| |
The decomposition left each big step function as a thin list of sub-step
calls with no runtime coverage. These tests sed-extract each orchestrator,
stub its sub-functions as recorders, and assert the exact call order, so a
dropped or reordered step fails the suite. configure_snapshots also gets a
per-filesystem dispatch check (zfs / btrfs / other).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The big step functions mixed many concerns in one body, with
essential_services the worst at 442 lines spanning randomness, networking,
SSH, firewall, service discovery, scheduling, and a 177-line filesystem-
branched snapshot block.
I split five of them into thin orchestrators that call named sub-functions,
one per concern:
- essential_services into 11 sub-steps; the snapshot block further splits
into configure_zfs_snapshots / configure_btrfs_snapshots behind a
dispatcher.
- prerequisites into bootstrap_pacman_keyring, install_required_software,
configure_build_environment, configure_package_mirrors.
- developer_workstation into per-category installers.
- boot_ux into one function per hardware-conditional concern (efi perms,
nvme module, initramfs hook, encrypted autologin, TLP, firmware trim,
GRUB).
- user_customizations into clone, stow, waybar prune, desktop caches,
dconf, finalize, directory creation.
Each sub-function body is a verbatim slice of the original (no
re-indentation, so heredoc bodies stay byte-identical). I verified each
extraction by asserting the slices, concatenated in call order, reproduce
the original body exactly, so no line is lost or reordered. bash -n is
clean, the unit suite stays green, and shellcheck gains no real findings.
The SC2329 "never invoked" notes on the new functions are the same
indirect-dispatch false positive every step function already carries.
The flat installers (desktop_environment, supplemental_software) and the
linear preflight_checks are left whole: their length is a sequence of
independent installs or checks, not mixed concerns, so splitting would
scatter a linear read behind indirection.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The installer announced, ran, and warned on each operation with a
hand-written two-line pair, repeated ~35 times:
action="enabling rngd service" && display "task" "$action"
systemctl enable rngd >> "$logfile" 2>&1 || error_warn "$action" "$?"
I added a run_task "desc" cmd... helper that does this in one line, plus an
enable_service wrapper for the canonical "enabling <unit> service" case. The
35 single-command sites now call run_task. The three exact-wording service
enables (rngd, upower, fail2ban) use enable_service. Multi-line sites
(heredocs, subshells, intervening logic) keep the explicit form.
Behavior is unchanged: same descriptions, same commands, same logfile
redirection, same non-fatal warning on the real exit code. tests/run-task
covers the helper across Normal/Boundary/Error including exit-code
propagation, and the full unit suite stays green.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
Marked the bare-metal-migration + shell-sweep task DONE and archived the resolved subtrees. Imported the scratchpad focus-follows-mouse bug from the roam inbox. Filed archangel's handoff replies (zfs-dkms delivered, heads-up adopted) to the outbox.
|
| | |
|
| |
|
|
|
|
| |
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 base image ships the full unsorted worldwide mirrorlist (hundreds of mirrors), and archsetup only configured reflector's timer, so the install ran every download against that list. pacman then stalled for many minutes on a slow or unresponsive mirror during the package installs. archsetup now runs reflector once before the heavy installs, curating a few fast recently-synced HTTPS mirrors and refreshing the databases against them. The run is bounded by `timeout` and non-fatal, so a flaky mirror-status service falls back to the base list instead of blocking the install.
Surfaced by the ZFS VM test path, where a worldwide-list mirror stalled a full run at the ditaa/JRE download.
|
| |
|
|
|
|
| |
User-level makepkg reads /etc/pacman.conf to resolve dependencies, so a root-only file makes every AUR build (starting with yay) fail with "could not be read: Permission denied". A current archangel ISO ships the base pacman.conf as 0600. archsetup already edits the file (ParallelDownloads, Color, multilib), so it now chmods it back to 0644, the Arch default, before the AUR installer runs.
The ZFS VM test path surfaced this on a fresh archangel base. The older btrfs base shipped it 0644.
|
| |
|
|
|
|
| |
An archangel-installed base ships informant, which registers a pacman PreTransaction hook (AbortOnFail) that blocks every package transaction until Arch news is marked read. archsetup's first transaction (the keyring reinstall) tripped it and the script halted at the bootstrap step. archsetup now marks all news read up front with `informant read --all` so the keyring, refresh, and install steps proceed. The --all flag marks without printing or prompting. A bare `informant read` is interactive and would hang an unattended run. The guard is a no-op when informant isn't installed.
The new ZFS VM test path surfaced this. Its base image comes from a current archangel ISO that includes informant, and the older btrfs base predated it.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
Adds a design note for building a ZFS base VM via archangel with a filesystem
profile selector (so make test covers the ZFS install path, currently only
exercised on bare metal), migrating run-test-baremetal.sh to key auth and the
Testinfra sweep, and then deleting the dead shell-sweep functions. Links it
from the bare-metal migration follow-up.
|
| |
|
|
|
|
| |
Final fresh make test passed green (96 passed, 10 skipped) with Testinfra as
the authoritative post-install validator. Records the end-state and the three
bugs the work surfaced and fixed.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
Plan to port the VM harness's shell validation sweep (validation.sh, ~26 checks) to Testinfra + pytest for more expressive checks and better reporting, then expand coverage to the parts of archsetup that aren't validated today.
Records the design: where pytest fits in run-test.sh, the SSH connection model (inject a throwaway test key), preserving the three-way issue attribution via pytest markers, smoke/integration tiering, a parity-then-expand migration, and a Goss comparison.
|
| |
|
|
|
|
|
|
| |
Add a backup_system_file helper that snapshots a pre-existing file to <path>.archsetup.bak before archsetup edits it in place, so a botched edit to fstab, mkinitcpio.conf, or sudoers is recoverable. It is idempotent: it never overwrites an existing backup, so the pristine original survives repeated edits within a run and across re-runs. It uses cp -p to preserve mode and ownership.
Only the in-place sed and append edits to pre-existing files route through it (locale.gen, makepkg.conf, pacman.conf, sudoers, wireless-regdom, geoclue.conf, pacman-contrib, fstab, mkinitcpio.conf, vconsole.conf). The brand-new drop-in files archsetup fully owns are skipped: there is no prior state to save, and recovery is just deleting them.
Covered by tests/backup-system-file/ (Normal, Boundary, Error cases, including mode preservation and the no-overwrite guarantee).
|
| |
|
|
| |
Mark the waypaper --restore task DONE, add the relogin manual-test under "Manual testing and validation", and file a follow-up: set-wallpaper's mv detaches the waypaper config from its stow symlink.
|
| |
|
|
|
|
|
| |
- Restore the dropped "Collapsible waybar sides" heading. Its drawer and body were orphaned when an earlier edit clobbered the heading line.
- Re-stamp the oldest-unreviewed task batch; drop "security education" to [#C]; tag the bridge-font and wallpaper-restore items.
- Close the Proton Mail Bridge font task (UI font scaled via QT_FONT_DPI).
- Archive two resolved inbox items to assets/outbox/.
|
| | |
|
| | |
|
| |
|
|
| |
Claimed the dirvish-wallpaper item from the roam inbox (it's a Wayland wallpaper-utility issue). Filed it with the awww/set-wallpaper findings and handed the Emacs dirvish-command piece to that project. Closed the four next-set tasks: the device-udev flag, SPDX headers, boolean-comparison style, and the mpd playlist_directory split.
|
| |
|
|
|
|
|
|
| |
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 first note said the system dconf db fixed it, but that left the running session white: a system-db default emits no change signal, so the appearance portal kept reporting no-preference, and libadwaita reads the portal, not GTK_THEME. The working fix added a user-level color-scheme set to signal the portal live.
|
| |
|
|
| |
Closed four solo tasks: nautilus dark theming (velox was missing the system dconf db that archsetup already declares), the CLI-tools install, the waybar tray-spacing fix, and the calendar-hover month/year highlight. Recorded the python-lyricsgenius recheck, which stays open: it still needs --skipinteg, but the cause moved from an expired PGP signature to a drifting LICENSE.txt checksum.
|
| |
|
|
|
|
| |
I adopted four modern CLI tools after the 2026-06-10 evaluation: bat (syntax-highlighting cat), dust (proportional disk-usage tree), hyperfine (statistical benchmarking), and doggo (a DNS client that speaks DoH/DoT/DoQ). tealdeer was already declared. All four are in extra and go in the General Utilities block.
I also corrected the python-lyricsgenius --skipinteg note. The original expired-signature cause is gone (the package tarball verifies now), but makepkg still fails integrity on a LICENSE.txt the PKGBUILD pulls from github master, so the workaround stays for a different reason than the old comment claimed.
|
| |
|
|
|
|
| |
Closed the three resolved tool-evaluation tasks into actionable work: adopt the modern CLI tools, migrate the terminal from foot to ghostty, and keep nautilus over yazi. Closed the org-capture popup task as sized to the scratchpad. Demoted nine undated high-priority sub-tasks to B per the priority scheme. Folded the wlogout laptop-test task into the rectangular-buttons task and tagged the whole waybar cluster :waybar: so it filters as a unit.
Reviewed the seven oldest-unreviewed tasks and kept all seven. Filed two new waybar tasks (calendar-hover highlight, idle-inhibitor rename) and folded a timer/stopwatch/alarm scope expansion into the existing waybar timer task.
|