The shipped irserver is a 32-bit ARM binary linked against libzip.so.4, which only
exists on armhf with Debian 12 or older. On a 64-bit userland or trixie it cannot run,
so the role now compiles the bundled 2019 sources on the device there, with GCC 14's
new hard errors (implicit declarations, implicit int, pointer/int mix-ups) downgraded
rather than the old code patched. Picked from `dpkg --print-architecture` and the
distribution version; `pi_irserver_build_from_source: true|false` forces it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Several roles reported "changed" on every playbook run even when
nothing on the target had drifted, making real config drift
indistinguishable from noise:
- 7 systemd tasks across 6 roles used state:restarted, which always
issues a restart and always reports changed. Switched to
state:started plus notify-driven handlers that only restart when
the underlying unit file, script, or config actually changes.
- pi_standard_setup's boot mode, timezone, and locale tasks shelled
out to raspi-config with changed_when:true hardcoded. Boot mode now
checks systemctl get-default first; timezone/locale now use the
natively idempotent community.general.timezone/locale_gen modules.
- The pi account password task computed password_hash('sha512')
without a seed, generating a new random salt (and thus an
apparently different hash) on every run. Added a stable seed so the
hash only changes when the underlying secret does.
Also renamed a mislabeled task in pi_squeezelite_custom and fixed a
typo in pi_standard_setup while those files were already touched.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- risky-file-permissions (32): add explicit mode: to copy/template/file tasks,
matching the umask-derived permissions they already had (0644 for configs
and systemd units, 0755 for created directories) — no functional change.
- var-naming (28): prefix role-scoped vars with their role name across
pi_dhtsensor, pi_dhtsensor_circuitpython, pi_shairport, pi_squeezelite,
pi_squeezelite_custom, pi_sispmctl, pi_standard_setup, and pi_sysdweb's
sysdweb_name (shared by 9 consuming roles). Updated every dependent
template, task reference, and matching inventory.yml override, and
verified resolved values with ansible-inventory before/after.
- Fixes a latent bug found while renaming: pi_standard_setup's "Get/Change
WiFi country" tasks reused the name wifi_country for both the role default
and a register, so the register silently clobbered the default before
do_wifi_country ever read it. Split into distinct names so the intended
default value is used.
- package-latest (2): pin docker-ce/docker-compose-plugin installs in
server_debian_docker to state: present.
- no-handler (1): move pi_lirc's "Reboot if boot overlay changed" into a
proper handler notified by the boot-overlay task.
ansible-lint now passes clean at the production profile.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Auto-fix FQCN, YAML formatting, jinja spacing, and free-form module
syntax via ansible-lint --fix
- Fix comments misplaced inside module args by the auto-fixer
(bluetooth-monitor, pi_standard_setup, pi_musicmouse)
- Fix notify: references left stale (lowercase) after handler names
were re-cased, which would have silently broken reboot/restart
handlers (pi_disable_onboard_bluetooth, pi_hifiberry_amp,
pi_squeezelite, pi_standard_setup)
- Fix a task in pis/debmatic-install.yml missing its module name
(apt_repository), which caused a real syntax-check failure
- Add missing play names, fix comment spacing, literal-compare idiom,
and no-changed-when annotations
- Delete unused/broken roles/better-shell-env (unreferenced, invalid YAML)
- Rename all hyphenated role directories to underscore form to satisfy
ansible-lint's role-name rule, updating every playbook/meta reference
Remaining lint findings (var-naming, package-latest, risky-file-permissions,
no-handler) intentionally left for follow-up per user decision.