--- # cv role — download and extract the CV release tarball into cv_content_dir. # Caddy serves the directory directly; there is no daemon to manage. # # Idempotency: a sentinel file records the installed cv_version. The # download/extract steps only run when the sentinel doesn't match cv_version. # # We use curl rather than ansible.builtin.get_url because the forge generic- # packages endpoint returns 405 on HEAD requests, which get_url issues before # downloading. - name: Ensure cv home exists ansible.builtin.file: path: "{{ cv_home }}" state: directory mode: '0755' - name: Read installed cv version sentinel ansible.builtin.slurp: src: "{{ cv_version_sentinel }}" register: cv_installed_raw failed_when: false changed_when: false - name: Set installed cv version fact ansible.builtin.set_fact: cv_installed_version: >- {{ (cv_installed_raw.content | b64decode).strip() if (cv_installed_raw.content is defined) else '' }} - name: Recreate cv content dir ansible.builtin.file: path: "{{ cv_content_dir }}" state: "{{ item }}" mode: '0755' loop: - absent - directory when: cv_installed_version != cv_version - name: Download and extract cv release tarball ansible.builtin.shell: cmd: >- set -euo pipefail; curl -fsSL {{ cv_release_url | quote }} -o {{ cv_home }}/cv.tar.gz && tar -xzf {{ cv_home }}/cv.tar.gz -C {{ cv_content_dir }} && rm -f {{ cv_home }}/cv.tar.gz executable: /bin/bash when: cv_installed_version != cv_version changed_when: true - name: Write cv version sentinel ansible.builtin.copy: content: "{{ cv_version }}\n" dest: "{{ cv_version_sentinel }}" mode: '0644' when: cv_installed_version != cv_version