Raspberry Pi OS ships a 64-bit kernel with a 32-bit userland, so uname -m - and
therefore ansible_architecture - reports aarch64 on a box whose /bin/ls is
ELF32 ARM and which has no /lib/ld-linux-aarch64.so.1. The aarch64 uv tarball
unpacked happily and then failed three tasks later with
/usr/local/bin/uv: No such file or directory
which is the dynamic loader missing, not the file, and points at entirely the
wrong thing. Pick the target triple from ansible_userspace_bits instead, which
is the fact that tells the truth, and key the install directory on the triple as
well as the version - otherwise `creates:` would keep a wrong-architecture
binary in place forever. Then run `uv --version` right after installing it, so a
bad download fails where the cause is visible.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
151 lines
5.1 KiB
YAML
151 lines
5.1 KiB
YAML
---
|
|
- name: Packages
|
|
ansible.builtin.apt:
|
|
name:
|
|
- git
|
|
- libvlc5 # runtime lib python-vlc (installed into the venv by uv) binds against
|
|
- vlc-plugin-base
|
|
- alsa-utils
|
|
- samba
|
|
cache_valid_time: 7200
|
|
|
|
- name: Ensure uv install directory exists
|
|
ansible.builtin.file:
|
|
path: "/opt/uv-{{ pi_musicmouse_uv_version }}-{{ pi_musicmouse_uv_target }}"
|
|
state: directory
|
|
mode: "0755"
|
|
|
|
- name: Download and extract uv {{ pi_musicmouse_uv_version }}
|
|
ansible.builtin.unarchive:
|
|
src: "https://github.com/astral-sh/uv/releases/download/{{ pi_musicmouse_uv_version }}/uv-{{ pi_musicmouse_uv_target }}.tar.gz"
|
|
dest: "/opt/uv-{{ pi_musicmouse_uv_version }}-{{ pi_musicmouse_uv_target }}"
|
|
remote_src: true
|
|
extra_opts: ["--strip-components=1"]
|
|
creates: "/opt/uv-{{ pi_musicmouse_uv_version }}-{{ pi_musicmouse_uv_target }}/uv"
|
|
|
|
- name: Symlink uv/uvx into /usr/local/bin
|
|
ansible.builtin.file:
|
|
src: "/opt/uv-{{ pi_musicmouse_uv_version }}-{{ pi_musicmouse_uv_target }}/{{ item }}"
|
|
dest: "/usr/local/bin/{{ item }}"
|
|
state: link
|
|
force: true
|
|
loop:
|
|
- uv
|
|
- uvx
|
|
|
|
- name: Verify uv runs on this host
|
|
ansible.builtin.command:
|
|
cmd: /usr/local/bin/uv --version
|
|
register: pi_musicmouse_uv_version_out
|
|
changed_when: false
|
|
|
|
- name: Checkout Musicmouse repo
|
|
ansible.builtin.git:
|
|
repo: "{{ pi_musicmouse_repo }}"
|
|
dest: /opt/musicmouse
|
|
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:
|
|
path: /opt/musicmouse/python-backend/pyproject.toml
|
|
register: pi_musicmouse_pyproject
|
|
# Meaningless under --check on a host that has never been deployed: the git task
|
|
# above reports "changed" without writing anything, so there is nothing to stat.
|
|
when: not ansible_check_mode
|
|
|
|
- name: Fail on a pre-rearchitecture checkout
|
|
ansible.builtin.fail:
|
|
msg: >-
|
|
{{ musicmouse_version }} has no python-backend/pyproject.toml, so it predates the
|
|
rearchitecture and this role cannot install it - the venv, the systemd unit and
|
|
the web/ build all live somewhere else on those commits. Point
|
|
musicmouse_version at a branch that has it (deploy/musicdolphin), or set
|
|
mediapi_install_kidsmusic to false for this host and leave whatever is installed
|
|
alone. Stopping here rather than failing three tasks deeper with the real reason
|
|
buried.
|
|
when: not ansible_check_mode and not pi_musicmouse_pyproject.stat.exists
|
|
|
|
- name: Create virtualenv with Python {{ pi_musicmouse_python_version }}
|
|
ansible.builtin.command:
|
|
cmd: "/usr/local/bin/uv venv --python {{ pi_musicmouse_python_version }} /opt/musicmouse/.venv"
|
|
creates: /opt/musicmouse/.venv/bin/python
|
|
|
|
- name: Create media directory
|
|
ansible.builtin.file:
|
|
path: /media/musicmouse
|
|
state: directory
|
|
mode: "0755"
|
|
|
|
- name: Install config file
|
|
ansible.builtin.copy:
|
|
src: "{{ pi_musicmouse_config_file }}"
|
|
dest: /media/musicmouse/config.yml
|
|
mode: "0644"
|
|
# Install-once: the app writes this file itself (parent mode's volume keys, the
|
|
# remote-control mapping). See pi_musicmouse_force_config in defaults.
|
|
force: "{{ pi_musicmouse_force_config }}"
|
|
notify: Restart musicmouse
|
|
|
|
- name: Install tippen curriculum
|
|
ansible.builtin.copy:
|
|
src: "{{ pi_musicmouse_curriculum_file }}"
|
|
dest: /media/musicmouse/tippen-curriculum.yml
|
|
mode: "0644"
|
|
when: pi_musicmouse_curriculum_file | length > 0
|
|
notify: Restart musicmouse
|
|
|
|
- name: Install systemd service file (from the checked-out repo, not a copy kept here)
|
|
ansible.builtin.copy:
|
|
src: /opt/musicmouse/python-backend/musicmouse.service
|
|
dest: /etc/systemd/system/musicmouse.service
|
|
mode: "0644"
|
|
remote_src: true
|
|
notify: Restart musicmouse
|
|
|
|
- name: Add script to autostart and start now
|
|
ansible.builtin.systemd:
|
|
name: musicmouse
|
|
state: started
|
|
enabled: "yes"
|
|
daemon_reload: "yes"
|
|
|
|
- name: Ensure local frontend build cache directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ pi_musicmouse_build_cache }}/{{ musicmouse_version | regex_replace('/', '_') }}"
|
|
state: directory
|
|
mode: "0755"
|
|
delegate_to: localhost
|
|
become: false
|
|
|
|
- name: Checkout Musicmouse repo for frontend build (control machine)
|
|
ansible.builtin.git:
|
|
repo: "{{ pi_musicmouse_repo }}"
|
|
dest: "{{ pi_musicmouse_build_cache }}/{{ musicmouse_version | regex_replace('/', '_') }}"
|
|
version: "{{ musicmouse_version }}"
|
|
accept_hostkey: true
|
|
force: true
|
|
delegate_to: localhost
|
|
become: false
|
|
notify: Build frontend
|
|
|
|
- name: Samba setup
|
|
ansible.builtin.copy:
|
|
src: smb.conf
|
|
dest: /etc/samba/
|
|
mode: "0644"
|
|
|
|
- name: Restart samba
|
|
ansible.builtin.systemd:
|
|
name: smbd
|
|
state: restarted
|
|
enabled: "yes"
|
|
daemon_reload: "yes"
|
|
# manual steps:
|
|
# - set samba passwords with smbpasswd
|
|
# - copy music into /media/musicmouse: scripts/sync-library.sh in the app repo, which
|
|
# also carries the cover and analysis cache over (or use the samba share, and let
|
|
# the device spend the DSP time itself)
|