<feed xmlns='http://www.w3.org/2005/Atom'>
<title>archsetup/scripts/testing/run-test.sh, branch claude/hungry-franklin-09fffc</title>
<subtitle>Builds a full dev workstation from a bare Arch Linux install.
</subtitle>
<id>https://git.cjennings.net/archsetup/atom?h=claude%2Fhungry-franklin-09fffc</id>
<link rel='self' href='https://git.cjennings.net/archsetup/atom?h=claude%2Fhungry-franklin-09fffc'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/'/>
<updated>2026-07-25T20:00:44+00:00</updated>
<entry>
<title>refactor(test): share runner and scenario contracts</title>
<updated>2026-07-25T20:00:44+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-25T20:00:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=f2a47add15a75a9f8bde3c6e3bd800cd281aa8bb'/>
<id>urn:sha1:f2a47add15a75a9f8bde3c6e3bd800cd281aa8bb</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix(test): harden four VM-framework paths from the S5 audit</title>
<updated>2026-07-21T04:40:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-21T04:40:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=e58a83cc3a1c7e6ec8225532169adbffecd04ea3'/>
<id>urn:sha1:e58a83cc3a1c7e6ec8225532169adbffecd04ea3</id>
<content type='text'>
init_vm_paths suffixed the disk and NVRAM by FS_PROFILE but left PID_FILE, MONITOR_SOCK, and SERIAL_LOG shared. A concurrent btrfs and zfs run read each other's PID file, so the second run's stop logic could kill the first run's VM. All runtime paths now carry the suffix.

kill_qemu sent kill -9 and returned without waiting, so the force-kill fallback could run qemu-img snapshot against a qcow2 the dying qemu still held locked (the restore failed silently behind || true, leaving the base image dirty). It now reaps or polls the process to death before returning.

debug-vm.sh hardcoded the btrfs base-disk name, so FS_PROFILE=zfs booted the wrong base or fatalled. It now takes DISK_PATH from init_vm_paths.

Both runners reported a completion-marker grep as "ArchSetup Exit Code," but the installer runs detached with set -e off, so its real exit status was never captured -- a run that errored mid-way and still reached its last line reported exit 0. The flag is now ARCHSETUP_COMPLETED with the report labeled honestly; Testinfra stays the pass/fail authority.
</content>
</entry>
<entry>
<title>test(archsetup): add FS_PROFILE selector for ZFS VM coverage</title>
<updated>2026-06-25T16:21:15+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-25T16:21:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=4c8a2216f34fc2502da5644a8cfc614b76efc4a8'/>
<id>urn:sha1:4c8a2216f34fc2502da5644a8cfc614b76efc4a8</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(testing): raise the install monitor timeout to 150 minutes</title>
<updated>2026-06-25T12:35:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-25T12:35:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=e17870ff2b9c2ebbc16b62f7664537b686ad356b'/>
<id>urn:sha1:e17870ff2b9c2ebbc16b62f7664537b686ad356b</id>
<content type='text'>
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 -&gt; 150 minutes) so a slow-but-healthy install completes.
</content>
</entry>
<entry>
<title>test(archsetup): make Testinfra the authoritative validator (P3 cutover)</title>
<updated>2026-06-25T07:39:10+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-25T07:39:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=980eebf8e30046706e6a6084af3202ab0dcb2bfa'/>
<id>urn:sha1:980eebf8e30046706e6a6084af3202ab0dcb2bfa</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(testing): authorize a root key so make test survives sshd hardening</title>
<updated>2026-06-25T05:24:33+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-25T05:24:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=b6d20c99971a44e5de67c962ab53987493578d6d'/>
<id>urn:sha1:b6d20c99971a44e5de67c962ab53987493578d6d</id>
<content type='text'>
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 &lt;key&gt; 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.
</content>
</entry>
<entry>
<title>test(archsetup): scaffold Testinfra post-install validation (P1)</title>
<updated>2026-06-25T04:54:53+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-25T04:54:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=6b24bbe4248fb2a459fdc22f0c52c075dee9b612'/>
<id>urn:sha1:6b24bbe4248fb2a459fdc22f0c52c075dee9b612</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>chore: open-source release-prep (udev flag, SPDX headers, boolean style)</title>
<updated>2026-06-24T23:44:29+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T23:44:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=b44992e498c4f3f290cef30070e50e1487752d65'/>
<id>urn:sha1:b44992e498c4f3f290cef30070e50e1487752d65</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>refactor(testing): clone the dotfiles repo into the VM test</title>
<updated>2026-05-22T20:52:24+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-22T20:52:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=89e959a9cf2cac30ae356beb53e981743b20f2fd'/>
<id>urn:sha1:89e959a9cf2cac30ae356beb53e981743b20f2fd</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix: correct a POSIX-sh bashism in init and document two SC2034 cases</title>
<updated>2026-05-20T17:02:47+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-20T17:02:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=6bca971185ffc95b54c14d53de384e48d4b35b3a'/>
<id>urn:sha1:6bca971185ffc95b54c14d53de384e48d4b35b3a</id>
<content type='text'>
init runs under #!/bin/sh but used $(&lt;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.
</content>
</entry>
</feed>
