From 56a93411def62348f5e9af185c61d7f1c96fc2f0 Mon Sep 17 00:00:00 2001 From: Trey Blancher Date: Mon, 6 Apr 2026 10:13:20 -0400 Subject: [PATCH] Initial commit of roles-refactor branch --- roles/arch_update/tasks/aur_upgrade.yaml | 13 +++ roles/arch_update/tasks/main.yaml | 17 ++++ roles/arch_update/tasks/python_check.yaml | 11 +++ roles/arch_update/tasks/repo_upgrade.yaml | 5 ++ roles/debian_update/tasks/apt_upgrade.yaml | 5 ++ roles/debian_update/tasks/main.yaml | 1 + roles/reboot/files/check_reboot.zsh | 94 ++++++++++++++++++++++ roles/reboot/handlers/main.yaml | 15 ++++ roles/reboot/tasks/main.yaml | 10 +++ 9 files changed, 171 insertions(+) create mode 100644 roles/arch_update/tasks/aur_upgrade.yaml create mode 100644 roles/arch_update/tasks/main.yaml create mode 100644 roles/arch_update/tasks/python_check.yaml create mode 100644 roles/arch_update/tasks/repo_upgrade.yaml create mode 100644 roles/debian_update/tasks/apt_upgrade.yaml create mode 100644 roles/debian_update/tasks/main.yaml create mode 100644 roles/reboot/files/check_reboot.zsh create mode 100644 roles/reboot/handlers/main.yaml create mode 100644 roles/reboot/tasks/main.yaml diff --git a/roles/arch_update/tasks/aur_upgrade.yaml b/roles/arch_update/tasks/aur_upgrade.yaml new file mode 100644 index 0000000..0141c22 --- /dev/null +++ b/roles/arch_update/tasks/aur_upgrade.yaml @@ -0,0 +1,13 @@ +--- +- name: AUR upgrade + aur: + use: pikaur + upgrade: true + aur_only: true + +- name: Rebuild AUR Python packages if version changed + ansible.builtin.import_tasks: aur_rebuild.yml + vars: + package_pattern: python + when: new_python is version(orig_python, '>', version_type='strict') + diff --git a/roles/arch_update/tasks/main.yaml b/roles/arch_update/tasks/main.yaml new file mode 100644 index 0000000..a9189ea --- /dev/null +++ b/roles/arch_update/tasks/main.yaml @@ -0,0 +1,17 @@ +--- +- name: Get original Python version + ansible.builtin.include_tasks: python_check.yaml + vars: + target_var: orig_python + +- name: Perform official repository updates + ansible.builtin.import_tasks: repo_upgrade.yaml + +- name: Get new Python version + ansible.builtin.include_tasks: python_check.yaml + vars: + target_var: new_python + +- name: Perform AUR updates and rebuilds + ansible.builtin.import_tasks: aur_update.yml + diff --git a/roles/arch_update/tasks/python_check.yaml b/roles/arch_update/tasks/python_check.yaml new file mode 100644 index 0000000..1fa2d97 --- /dev/null +++ b/roles/arch_update/tasks/python_check.yaml @@ -0,0 +1,11 @@ +--- +- name: Run Python version command + ansible.builtin.shell: + cmd: python --version | grep -Po '\d+\.\d+' + register: _temp_python_version + changed_when: false + +- name: Assign version to dynamic variable + ansible.builtin.set_fact: + "{{ target_var }}": "{{ _temp_python_version.stdout }}" + diff --git a/roles/arch_update/tasks/repo_upgrade.yaml b/roles/arch_update/tasks/repo_upgrade.yaml new file mode 100644 index 0000000..dc61611 --- /dev/null +++ b/roles/arch_update/tasks/repo_upgrade.yaml @@ -0,0 +1,5 @@ +- name: Full repository upgrade + become: true + community.general.pacman: + update_cache: true + upgrade: true diff --git a/roles/debian_update/tasks/apt_upgrade.yaml b/roles/debian_update/tasks/apt_upgrade.yaml new file mode 100644 index 0000000..8e980ca --- /dev/null +++ b/roles/debian_update/tasks/apt_upgrade.yaml @@ -0,0 +1,5 @@ +- name: Full system upgrade + become: true + ansible.builtin.apt: + update_cache: true + upgrade: full diff --git a/roles/debian_update/tasks/main.yaml b/roles/debian_update/tasks/main.yaml new file mode 100644 index 0000000..c139aa5 --- /dev/null +++ b/roles/debian_update/tasks/main.yaml @@ -0,0 +1 @@ +- name: Perform official repository updates ansible.builtin.import_tasks: apt_upgrade.yaml diff --git a/roles/reboot/files/check_reboot.zsh b/roles/reboot/files/check_reboot.zsh new file mode 100644 index 0000000..8ff7599 --- /dev/null +++ b/roles/reboot/files/check_reboot.zsh @@ -0,0 +1,94 @@ +#!/usr/bin/env zsh + +# Exit code 0 = Reboot required +# Exit code 1 = System is up to date / No reboot needed + +# 1. Branch based on detected distro +if [[ -f /etc/os-release ]]; then + source /etc/os-release +else + echo "Cannot determine OS." + exit 1 +fi + +# ========================================== +# DEBIAN LOGIC +# ========================================== +if [[ "$ID" == "debian" || "$ID_LIKE" == *"debian"* ]]; then + # Debian automatically creates this file when a kernel, microcode, + # or core library update requires a reboot. + if [[ -f /var/run/reboot-required ]]; then + exit 0 + else + exit 1 + fi + +# ========================================== +# ARCH LINUX LOGIC +# ========================================== +elif [[ "$ID" == "arch" || "$ID_LIKE" == *"arch"* ]]; then + + # --- KERNEL CHECK --- + # Get the currently running kernel version + current_kernel=$(uname -r) + + # Determine the installed kernel package based on the running kernel's name + # e.g., "6.1.60-1-lts" -> "linux-lts", "6.5.9-arch1-1" -> "linux" + if [[ "$current_kernel" == *"-lts" ]]; then + kernel_pkg="linux-lts" + elif [[ "$current_kernel" == *"-zen" ]]; then + kernel_pkg="linux-zen" + elif [[ "$current_kernel" == *"-hardened" ]]; then + kernel_pkg="linux-hardened" + else + kernel_pkg="linux" + fi + + # Get the installed version from pacman. + # Note: pacman uses periods (6.5.9.arch1-1) while uname uses dashes (6.5.9-arch1-1). + # We strip the package name and format it to match `uname -r` for a clean comparison. + installed_kernel=$(pacman -Q "$kernel_pkg" | awk '{print $2}' | sed 's/\./-/g' | sed 's/-\([^-]*\)$/.\1/') + + # In some UKI setups or specific Arch versions, the sed replacement above might not + # perfectly match `uname -r` format. A bulletproof fallback is checking if the + # modules directory for the currently running kernel has been removed by a pacman update. + if [[ ! -d "/usr/lib/modules/$current_kernel" ]]; then + exit 0 + fi + + # --- MICROCODE CHECK --- + # Check CPU vendor to determine which microcode package to look for + vendor=$(grep -m 1 'vendor_id' /proc/cpuinfo | awk '{print $3}') + if [[ "$vendor" == "GenuineIntel" ]]; then + ucode_pkg="intel-ucode" + elif [[ "$vendor" == "AuthenticAMD" ]]; then + ucode_pkg="amd-ucode" + else + ucode_pkg="" + fi + + if [[ -n "$ucode_pkg" ]]; then + # Check if the microcode package was updated recently by looking at the + # build date of the installed package vs the boot time of the system. + + # Get system boot time in seconds since epoch + boot_time=$(awk '{print int($1)}' /proc/uptime) + boot_epoch=$(( $(date +%s) - boot_time )) + + # Get the install time of the microcode package + ucode_install_epoch=$(expac '%time' "$ucode_pkg" 2>/dev/null || echo 0) + + # If the microcode was installed AFTER the system booted, reboot needed + if (( ucode_install_epoch > boot_epoch )); then + exit 0 + fi + fi + + # If we made it this far, neither kernel nor microcode triggered a reboot + exit 1 + +else + # Fallback for unsupported OS + exit 1 +fi + diff --git a/roles/reboot/handlers/main.yaml b/roles/reboot/handlers/main.yaml new file mode 100644 index 0000000..94733f0 --- /dev/null +++ b/roles/reboot/handlers/main.yaml @@ -0,0 +1,15 @@ +--- +- name: Temporarily stop Mollyguard to allow reboot + become: true + ansible.builtin.systemd: + name: mollyguard.service + state: stopped + listen: Reboot system + +- name: Execute System Reboot + become: true + ansible.builtin.reboot: + msg: "Reboot initiated by Ansible" + reboot_timeout: 600 + listen: Reboot system + diff --git a/roles/reboot/tasks/main.yaml b/roles/reboot/tasks/main.yaml new file mode 100644 index 0000000..1d2b5a9 --- /dev/null +++ b/roles/reboot/tasks/main.yaml @@ -0,0 +1,10 @@ +--- +- name: Check if kernel or microcode update requires reboot + ansible.builtin.script: check_reboot.zsh # Your script placed in files/ + register: reboot_check + # Prevent Ansible from failing if the script returns false (exit code 1) + failed_when: false + # Trigger the handler ONLY if the script returns true (exit code 0) + changed_when: reboot_check.rc == 0 + notify: Reboot system +