--- # roles/pfsense_upgrade/tasks/update_check.yml # Checks for available upgrades using pfSense-upgrade -c and pkg version. # Also queries upstream for the latest stable release on this branch. # --------------------------------------------------------------------------- # 1. Refresh the local pkg repository metadata # --------------------------------------------------------------------------- - name: Update pkg repository metadata ansible.builtin.raw: sudo pkg update -f 2>&1 register: _pkg_update changed_when: false when: pkg_repo_update | bool timeout: "{{ upgrade_check_timeout }}" # --------------------------------------------------------------------------- # 2. Run pfSense-upgrade in check-only mode # --------------------------------------------------------------------------- - name: Run pfSense-upgrade --check (dry run) ansible.builtin.raw: > sudo {{ pfsense_upgrade_bin }} -d -c 2>&1 register: _upgrade_check changed_when: false timeout: "{{ upgrade_check_timeout }}" # pfSense-upgrade exits 0 when up-to-date, non-zero when upgrade available. # We capture both cases. failed_when: false - name: Parse upgrade check output ansible.builtin.set_fact: upgrade_check_stdout: "{{ _upgrade_check.stdout | trim }}" upgrade_check_rc: "{{ _upgrade_check.rc }}" # True if the tool reports an update is available upgrade_available: >- {{ _upgrade_check.rc != 0 or 'Upgraded' in _upgrade_check.stdout or 'update' in _upgrade_check.stdout | lower and 'up to date' not in _upgrade_check.stdout | lower }} # Attempt to extract the new version string from the upgrade check output # pfSense-upgrade typically prints: "pfSense-upgrade: New version available: 2.7.3-RELEASE" upgrade_available_version: >- {{ _upgrade_check.stdout | regex_search('(\d+\.\d+\.\d+[-a-zA-Z0-9]*)', '\1') | first | default('unknown') }} # --------------------------------------------------------------------------- # 3. Check pkg for pending package updates (captures sub-component updates) # --------------------------------------------------------------------------- - name: Check for pending pkg upgrades (outdated packages) ansible.builtin.raw: sudo pkg version -l '<' 2>&1 | head -40 register: _pkg_outdated changed_when: false failed_when: false - name: Count outdated packages ansible.builtin.set_fact: pkg_outdated_count: "{{ _pkg_outdated.stdout_lines | reject('match', '^\\s*$') | list | length }}" pkg_outdated_list: "{{ _pkg_outdated.stdout | trim }}" # --------------------------------------------------------------------------- # 4. Detect the latest stable release for this branch via GitHub # --------------------------------------------------------------------------- - name: Fetch latest stable release version from Netgate/pfSense repo ansible.builtin.raw: > fetch -q -o - "{{ pfsense_release_url }}" 2>/dev/null || echo "fetch_failed" register: _upstream_version_raw changed_when: false failed_when: false - name: Parse upstream latest stable version ansible.builtin.set_fact: upstream_version: "{{ _upstream_version_raw.stdout | trim }}" upstream_fetch_ok: "{{ 'fetch_failed' not in _upstream_version_raw.stdout }}" - name: Derive upstream branch (major.minor) ansible.builtin.set_fact: upstream_major_minor: >- {{ upstream_version | regex_replace('^(\d+\.\d+).*$', '\1') | default(pfsense_major_minor) }} when: upstream_fetch_ok | bool # --------------------------------------------------------------------------- # 5. Compare branches — detect if a newer stable branch exists upstream # --------------------------------------------------------------------------- - name: Determine if a newer major release branch is available ansible.builtin.set_fact: new_major_release_available: >- {{ upstream_fetch_ok | bool and (upstream_major_minor | string) != (pfsense_major_minor | string) and (upstream_major_minor.split('.')[0] | int > pfsense_major_minor.split('.')[0] | int) or (upstream_major_minor.split('.')[0] | int == pfsense_major_minor.split('.')[0] | int and upstream_major_minor.split('.')[1] | int > pfsense_major_minor.split('.')[1] | int) }} when: upstream_fetch_ok | bool - name: Default new_major_release_available when fetch failed ansible.builtin.set_fact: new_major_release_available: false when: not (upstream_fetch_ok | bool) # --------------------------------------------------------------------------- # 6. Print the full update status report # --------------------------------------------------------------------------- - name: Display update status report ansible.builtin.debug: msg: - "============================================================" - " Update Status: {{ inventory_hostname }}" - "============================================================" - " Current version : {{ pfsense_current_version }}" - " Current branch : {{ pfsense_major_minor }}" - "------------------------------------------------------------" - " In-branch update : {{ 'YES — ' ~ upgrade_available_version if upgrade_available | bool else 'No — already up to date' }}" - " Outdated pkgs : {{ pkg_outdated_count }} package(s) behind" - "------------------------------------------------------------" - " Upstream latest : {{ upstream_version if upstream_fetch_ok | bool else 'Could not reach upstream' }}" - " Upstream branch : {{ upstream_major_minor if upstream_fetch_ok | bool else 'N/A' }}" - " New branch avail : {{ 'YES — ' ~ upstream_version if new_major_release_available | bool else 'No' }}" - "------------------------------------------------------------" - " perform_upgrade : {{ perform_upgrade | bool }}" - " allow_major_upg : {{ allow_major_upgrade | bool }}" - "============================================================" - name: Warn if a new major release branch is available but not allowed ansible.builtin.debug: msg: > WARNING: pfSense {{ upstream_version }} is available on branch {{ upstream_major_minor }}, which is newer than your running branch {{ pfsense_major_minor }}. To upgrade across branches, re-run with: -e "perform_upgrade=true allow_major_upgrade=true" when: - new_major_release_available | bool - not (allow_major_upgrade | bool) - name: Warn if perform_upgrade is false but upgrades are available ansible.builtin.debug: msg: > DRY RUN — upgrades are available but perform_upgrade=false. Re-run with -e "perform_upgrade=true" to apply. when: - (upgrade_available | bool) or (pkg_outdated_count | int > 0) - not (perform_upgrade | bool)