--- - name: Bootstrap — ensure Python is available hosts: linux_hosts gather_facts: false roles: - role: preflight tasks_from: bootstrap - name: Reboot Linux hosts if required (or forced) hosts: linux_hosts gather_facts: true vars: force_reboot: false # set to true in Semaphore extra vars to reboot regardless tasks: - name: Check if reboot is required (Debian/Ubuntu) ansible.builtin.stat: path: /var/run/reboot-required register: reboot_required_file when: ansible_os_family == "Debian" - name: Set reboot_needed fact (Debian/Ubuntu) ansible.builtin.set_fact: reboot_needed: "{{ reboot_required_file.stat.exists | default(false) }}" when: ansible_os_family == "Debian" - name: Check if reboot is required (Alpine) ansible.builtin.shell: | apk version -l = 2>/dev/null | grep -q kernel && echo "yes" || echo "no" register: alpine_reboot_check changed_when: false when: ansible_os_family == "Alpine" - name: Set reboot_needed fact (Alpine) ansible.builtin.set_fact: reboot_needed: "{{ alpine_reboot_check.stdout | trim == 'yes' }}" when: ansible_os_family == "Alpine" - name: Set reboot_needed fallback (RHEL or unknown) ansible.builtin.set_fact: reboot_needed: false when: reboot_needed is not defined - name: Report reboot status ansible.builtin.debug: msg: >- {{ inventory_hostname }}: reboot_needed={{ reboot_needed }}, force_reboot={{ force_reboot }} — {{ 'WILL reboot' if (reboot_needed or force_reboot) else 'Skipping reboot' }} - name: Reboot host ansible.builtin.reboot: reboot_timeout: 300 pre_reboot_delay: 10 post_reboot_delay: 30 msg: "Scheduled reboot — initiated by Ansible" when: reboot_needed | bool or force_reboot | bool - name: Reboot complete ansible.builtin.debug: msg: "{{ inventory_hostname }} is back online and responding" when: reboot_needed | bool or force_reboot | bool