<feed xmlns='http://www.w3.org/2005/Atom'>
<title>archsetup/scripts/testing/lib, branch main</title>
<subtitle>Builds a full dev workstation from a bare Arch Linux install.
</subtitle>
<id>https://git.cjennings.net/archsetup/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/archsetup/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/'/>
<updated>2026-06-11T17:57:49+00:00</updated>
<entry>
<title>fix(testing): lingering check could never pass — ls output broke the capture</title>
<updated>2026-06-11T17:57:49+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T17:57:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=5b519001a73d98ac7c1ab49256ac34781994f9e0'/>
<id>urn:sha1:5b519001a73d98ac7c1ab49256ac34781994f9e0</id>
<content type='text'>
The check captured 'ls path &amp;&amp; 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.
</content>
</entry>
<entry>
<title>fix(testing): key the portal-query skip on the compositor, close warning tasks</title>
<updated>2026-06-11T00:08:54+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T00:08:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=19015c77c7d059d7bbc65270c6985f6cbc2330a3'/>
<id>urn:sha1:19015c77c7d059d7bbc65270c6985f6cbc2330a3</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(testing): skip environment-impossible checks instead of warning</title>
<updated>2026-06-10T23:19:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T23:19:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=ced91c43c464d624b3396ae44894022fd33aecaf'/>
<id>urn:sha1:ced91c43c464d624b3396ae44894022fd33aecaf</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(testing): expect minimal/ tree for the .zshrc symlink on DESKTOP_ENV=none</title>
<updated>2026-06-10T21:35:26+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T21:35:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=1754a945fa58fbdf71561596e5ddf06dea7428be'/>
<id>urn:sha1:1754a945fa58fbdf71561596e5ddf06dea7428be</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(testing): expect ~/.dotfiles symlink target in dotfiles validation</title>
<updated>2026-05-23T01:34:03+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-23T01:34:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=13c300f6fa8e52c498bf9843f6b8b6f61cab935b'/>
<id>urn:sha1:13c300f6fa8e52c498bf9843f6b8b6f61cab935b</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix(testing): cleanup traps, arg validation, and two real bugs</title>
<updated>2026-05-17T19:38:40+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-17T19:38:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=663cec6520a72680609c0d803494fb0bde4ce765'/>
<id>urn:sha1:663cec6520a72680609c0d803494fb0bde4ce765</id>
<content type='text'>
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).
</content>
</entry>
<entry>
<title>chore(scripts): drop dead and superseded scripts</title>
<updated>2026-05-16T22:35:43+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-16T22:35:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=61bf3e7463c2e7f40874e718911f2bd6b86b859e'/>
<id>urn:sha1:61bf3e7463c2e7f40874e718911f2bd6b86b859e</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(testing): drop stale plugin checks, count failed validations</title>
<updated>2026-05-11T22:19:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-11T22:19:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=14eecb5b8e76cf1b1de20643d496dc94cfdce0ab'/>
<id>urn:sha1:14eecb5b8e76cf1b1de20643d496dc94cfdce0ab</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(archsetup): add rustup, log-cleanup cron, update configs</title>
<updated>2026-02-27T16:51:03+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-02-27T16:51:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=9f1481623d360ec189906ee0d806ec30914f7f24'/>
<id>urn:sha1:9f1481623d360ec189906ee0d806ec30914f7f24</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>chore(archsetup): add texlive-latexextra, update test scripts</title>
<updated>2026-02-12T22:09:25+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-02-12T22:09:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/archsetup/commit/?id=c6e1e7bd25285eff16ecfba88b388ddcf7769903'/>
<id>urn:sha1:c6e1e7bd25285eff16ecfba88b388ddcf7769903</id>
<content type='text'>
Add texlive-latexextra for pdflatex resume builds (enumitem package).
Update test VM password and Arch mirror URL. Process inbox items.
</content>
</entry>
</feed>
