--- # roles/upgrade/tasks/main.yml # # Async pattern: Tailscale may restart during upgrade, dropping SSH. # Fire and forget → poll status with unreachable tolerance + retries. - name: Upgrade all packages (Alpine) community.general.apk: upgrade: true update_cache: true async: 3600 poll: 0 register: alpine_upgrade # By default async job return change: true # Force adapting the change condition for idempotency changed_when: false when: ansible_facts['os_family'] == "Alpine" - name: Wait for Alpine upgrade ansible.builtin.async_status: jid: "{{ alpine_upgrade.ansible_job_id }}" register: alpine_result until: alpine_result.finished retries: 60 delay: 10 # By default async job return change: true # Force adapting the change condition for idempotency changed_when: alpine_result.changed | default(false) ignore_unreachable: true when: - ansible_facts['os_family'] == "Alpine" - alpine_upgrade.ansible_job_id is defined - name: Upgrade all packages (Debian) ansible.builtin.apt: upgrade: full update_cache: true async: 3600 poll: 0 register: debian_upgrade # By default async job return change: true # Force adapting the change condition for idempotency changed_when: false when: ansible_facts['os_family'] == "Debian" - name: Wait for Debian upgrade ansible.builtin.async_status: jid: "{{ debian_upgrade.ansible_job_id }}" register: debian_result until: debian_result.finished retries: 60 delay: 10 # By default async job return change: true # Force adapting the change condition for idempotency changed_when: debian_result.changed | default(false) ignore_unreachable: true when: - ansible_facts['os_family'] == "Debian" - debian_upgrade.ansible_job_id is defined