--- - name: "๐Ÿ” update (dnf) | make dnf retry transient mirror/egress failures natively" become: true ansible.builtin.lineinfile: path: /etc/dnf/dnf.conf regexp: "^retries=" line: "retries=10" insertafter: "^\\[main\\]" # Exception: under dnf5, ansible.builtin.dnf's update_cache expires no repo (it queries the repos before loading them), so cached metadata survives until metadata_expire. - name: "๐Ÿ”„ update (dnf) | re-fetch the metadata of every enabled repository" become: true ansible.builtin.command: argv: [dnf, makecache, --refresh] changed_when: false - name: "๐Ÿ”„ update (dnf) | upgrade all installed packages" block: - name: "๐Ÿ”„ update (dnf) | refresh dnf cache and upgrade all installed packages" ansible.builtin.dnf: # nocheck: dynamic-package - full-system upgrade, not a package install name: "*" state: latest update_cache: true rescue: - name: "๐Ÿ›‘ update (dnf) | re-raise anything but packages no mirror serves" # nocheck: rescue-recovery re-fetches metadata a mirror on the previous push served and retries once; the retry fails loud ansible.builtin.fail: msg: "{{ ansible_failed_result.msg }}" when: ansible_failed_result.msg is not match('Failed to download packages') - name: "๐Ÿงน update (dnf) | drop the metadata a mirror still on the previous push served" become: true ansible.builtin.command: argv: [dnf, clean, metadata] changed_when: true - name: "๐Ÿ”„ update (dnf) | upgrade once more against fresh metadata" ansible.builtin.dnf: # nocheck: dynamic-package - full-system upgrade, not a package install name: "*" state: latest update_cache: true