diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-08 06:17:31 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-08 06:17:31 -0500 |
| commit | bef70537fec8532f8f71c46e7f63ea09dcbd6bfb (patch) | |
| tree | 859fa143c8159ce97b2f6a38c5536701c3f9da55 | |
| parent | af5a27e1a0b374a932f4ad6c5e2ff5fbf53791ff (diff) | |
| download | archsetup-bef70537fec8532f8f71c46e7f63ea09dcbd6bfb.tar.gz archsetup-bef70537fec8532f8f71c46e7f63ea09dcbd6bfb.zip | |
feat(install): install maintenance thresholds and enable maint timers
The maint console and the system-health-check workflow grade against ~/.config/archsetup/maintenance-thresholds.toml, but nothing installed it. A fresh install got a working maint CLI and no thresholds file.
user_customizations now installs the shipped TOML from the cloned repo. A re-run refreshes it, and the user layer in ~/.config/maint/ is never touched, so a reinstall can't eat curation. It also enables maint-scan.timer and maint-net-scan.timer through wants-symlinks (systemctl --user has no session bus during install, the syncthing idiom). Timer enablement is hyprland-only because the units live in that stow tier.
The install lists gain the runtime tools the probes call but nothing carried: expac, lm_sensors, fwupd.
| -rwxr-xr-x | archsetup | 43 | ||||
| -rw-r--r-- | tests/installer-steps/test_orchestrators.py | 33 |
2 files changed, 75 insertions, 1 deletions
@@ -1210,6 +1210,7 @@ user_customizations() { refresh_desktop_caches configure_dconf_defaults finalize_dotfiles + install_maintenance_config create_user_directories } @@ -1358,6 +1359,45 @@ finalize_dotfiles() { } +install_maintenance_config() { + + display "subtitle" "Maintenance Console" + + install_maintenance_thresholds + if [[ "$desktop_env" == "hyprland" ]]; then + enable_maint_timers + fi +} + +install_maintenance_thresholds() { + # Shipped severity thresholds read by the maint console and the + # system-health-check workflow. This file is the shipped layer — a re-run + # refreshes it. User curation and overrides live in ~/.config/maint/, + # which archsetup never touches, so a reinstall can't eat curation. + action="installing maintenance thresholds" && display "task" "$action" + local src="${user_archsetup_dir:-/home/$username/code/archsetup}/configs/maintenance-thresholds.toml" + (install -d "/home/$username/.config/archsetup" && \ + install -m 0644 "$src" "/home/$username/.config/archsetup/maintenance-thresholds.toml" && \ + chown -R "$username:$username" "/home/$username/.config/archsetup") \ + >> "$logfile" 2>&1 || error_warn "$action" "$?" + +} + +enable_maint_timers() { + # The hyprland tier stows maint-scan.timer + maint-net-scan.timer as user + # units under ~/.config/systemd/user/. systemctl --user can't run during + # install (no user session bus), so create the enablement symlinks + # directly — same idiom as the syncthing user service. + action="enabling maint scan timers" && display "task" "$action" + local unit_dir="/home/$username/.config/systemd/user" + (mkdir -p "$unit_dir/timers.target.wants" && \ + ln -sf "$unit_dir/maint-scan.timer" "$unit_dir/timers.target.wants/maint-scan.timer" && \ + ln -sf "$unit_dir/maint-net-scan.timer" "$unit_dir/timers.target.wants/maint-net-scan.timer" && \ + chown -R "$username:$username" "/home/$username/.config/systemd") \ + >> "$logfile" 2>&1 || error_warn "$action" "$?" + +} + create_user_directories() { action="creating common directories" && display "task" "$action" # Create default directories and grant permissions @@ -1673,6 +1713,7 @@ configure_package_cache() { display "subtitle" "Package Repository Cache Maintenance" pacman_install pacman-contrib pacman_install arch-audit # CVE report from Arch Security Team data (maintenance console) + pacman_install expac # package metadata queries (maintenance console) run_task "enabling the package cache cleanup timer" systemctl enable --now paccache.timer action="configuring paccache to keep 3 versions" && display "task" "$action" @@ -2744,6 +2785,8 @@ supplemental_software() { pacman_install bind # DNS utilities (dig, host, nslookup) pacman_install net-tools # network tools (netstat for security auditing) pacman_install smartmontools # monitors hard drives + pacman_install lm_sensors # temperature sensors (maintenance console) + pacman_install fwupd # firmware update checks (maintenance console) pacman_install lynis # security auditing tool pacman_install telegram-desktop # messenger application # LaTeX - minimal set for document compilation with latexmk diff --git a/tests/installer-steps/test_orchestrators.py b/tests/installer-steps/test_orchestrators.py index 48b7508..2a771ba 100644 --- a/tests/installer-steps/test_orchestrators.py +++ b/tests/installer-steps/test_orchestrators.py @@ -51,7 +51,8 @@ ORCHESTRATORS = { "user_customizations": [ "clone_user_repos", "stow_dotfiles", "prune_waybar_battery", "refresh_desktop_caches", "configure_dconf_defaults", - "finalize_dotfiles", "create_user_directories", + "finalize_dotfiles", "install_maintenance_config", + "create_user_directories", ], } @@ -114,5 +115,35 @@ class SnapshotDispatch(unittest.TestCase): self.assertEqual(result.stdout.split(), []) +class MaintenanceConfigDispatch(unittest.TestCase): + """install_maintenance_config branches on desktop_env; pin each branch. + + The thresholds TOML installs for every environment (the CLI works + headless); the scan timers are user units in the hyprland stow tier, so + their enablement is hyprland-only. + """ + + SUBS = ["install_maintenance_thresholds", "enable_maint_timers"] + + def test_hyprland_installs_thresholds_and_enables_timers(self): + result = run_orchestrator( + "install_maintenance_config", self.SUBS, + extra_defs='desktop_env=hyprland', + ) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout.split(), self.SUBS) + + def test_non_hyprland_installs_thresholds_only(self): + for env in ("dwm", "none"): + with self.subTest(desktop_env=env): + result = run_orchestrator( + "install_maintenance_config", self.SUBS, + extra_defs=f'desktop_env={env}', + ) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout.split(), + ["install_maintenance_thresholds"]) + + if __name__ == "__main__": unittest.main() |
