diff --git a/roles/pi_musicmouse/handlers/main.yml b/roles/pi_musicmouse/handlers/main.yml index 082dbce..dc32403 100644 --- a/roles/pi_musicmouse/handlers/main.yml +++ b/roles/pi_musicmouse/handlers/main.yml @@ -1,10 +1,4 @@ --- -- name: Reinstall musicmouse backend - ansible.builtin.command: - cmd: "/usr/local/bin/uv pip install --python /opt/musicmouse/.venv/bin/python /opt/musicmouse/python-backend" - changed_when: true - notify: Restart musicmouse - - name: Build frontend ansible.builtin.command: cmd: npm ci diff --git a/roles/pi_musicmouse/tasks/main.yml b/roles/pi_musicmouse/tasks/main.yml index da65430..1b18a88 100644 --- a/roles/pi_musicmouse/tasks/main.yml +++ b/roles/pi_musicmouse/tasks/main.yml @@ -7,6 +7,11 @@ - vlc-plugin-base - alsa-utils - samba + # Pillow ships no armv7 wheel and Raspberry Pi OS's userland is 32-bit, so it is + # compiled from source here and needs its image headers. (piwheels would have a + # prebuilt one, but only for the system Python, not the 3.13 uv installs.) + - libjpeg-dev + - zlib1g-dev cache_valid_time: 7200 - name: Ensure uv install directory exists @@ -46,7 +51,6 @@ version: "{{ musicmouse_version }}" accept_hostkey: true force: true - notify: Reinstall musicmouse backend - name: Check the checkout has the layout this role knows ansible.builtin.stat: @@ -73,6 +77,18 @@ cmd: "/usr/local/bin/uv venv --python {{ pi_musicmouse_python_version }} /opt/musicmouse/.venv" creates: /opt/musicmouse/.venv/bin/python +- name: Install the backend into the venv + # Every run, not on a checkout change via a handler. Tied to the checkout, one failed + # run strands the device: the notification is dropped when the play fails, the next + # run finds the checkout already current and notifies nothing, and the venv stays + # empty while the service crash-loops on ModuleNotFoundError. uv is fast when there + # is nothing to do, and its output says whether there was. + ansible.builtin.command: + cmd: "/usr/local/bin/uv pip install --python /opt/musicmouse/.venv/bin/python /opt/musicmouse/python-backend" + register: pi_musicmouse_install + changed_when: "'Installed' in pi_musicmouse_install.stderr" + notify: Restart musicmouse + - name: Create media directory ansible.builtin.file: path: /media/musicmouse @@ -141,6 +157,22 @@ ansible_become: false # see the first delegated task in tasks/main.yml notify: Build frontend +- name: Check whether the device has a built frontend + ansible.builtin.stat: + path: /opt/musicmouse/web/dist/index.html + register: pi_musicmouse_dist + +- name: Queue a frontend build when the device has none + # The build chain hangs off the control machine's checkout changing, which has the + # same hole the backend install had: a run that fails after that checkout leaves the + # Pi with no dist, and every later run finds the checkout current and rebuilds + # nothing. Cheap to check, and it only fires when the device really has no UI. + ansible.builtin.debug: + msg: "No frontend at /opt/musicmouse/web/dist - queueing a build" + when: not pi_musicmouse_dist.stat.exists + changed_when: true + notify: Build frontend + - name: Samba setup ansible.builtin.copy: src: smb.conf