blueprint:
  name: Home Assistant Auto-update on a schedule base
  author: Edward Firmo (https://github.com/edwardtfn)
  homeassistant:
    min_version: 2024.8.0
  description: '# Home Assistant Auto-update

    Update Home Assistant automatically when a new update is available.

    v2024.9.30.0

    Attention:

    * Home Assistant may restart automatically as part of the update process.

    * **Use under your own risk!** Please see the discussions on Home Assistant community
    around the risks involved on auto-updating the system.

    For questions and suggestions, please use [this thread in Home Assistant Community
    portal](https://community.home-assistant.io/t/scheduled-auto-update-for-home-assistant/459281).

    '
  domain: automation
  source_url: https://raw.githubusercontent.com/edwardtfn/HomeAssistant-Config/main/blueprints/automation/EdwardTFN/auto_update_scheduled.yaml
  input:
    when_section:
      name: When (Schedule, etc.)
      icon: mdi:calendar
      description: Select when the updates should happen and when it should be skipped.
      collapsed: false
      input:
        schedule_entity:
          name: Schedule entity
          description: 'You can create an [Schedule](https://www.home-assistant.io/integrations/schedule)
            under [Settings > Devices & Services > Helpers](https://my.home-assistant.io/redirect/config_flow_start/?domain=schedule).

            Note => The schedule windows will define when an update will start. It
            is possible that a backup, an update or a restart process finishes after
            the schedule window, but new updates won''t stars outside the schedule
            windows.'
          default: []
          selector:
            entity:
              multiple: false
              domain:
              - schedule
              reorder: false
        schedule_monthday:
          name: Earliest day in the month to update Home Assistant (optional)
          description: 'Usually a new major version of Home Assistant is available
            on the begining of every month. Some people consider those releases as
            not stable enough and prefer to avoid those versions, not updating the
            system until the mid of the month (day 15).

            Note => If you select a day higher than 28 the updates won''t run every
            month.

            '
          default: 1
          selector:
            number:
              min: 1.0
              max: 31.0
              step: 1.0
              mode: slider
        update_out_of_schedule:
          name: Out of schedule entities (optional)
          description: You can select update entities which will be updated as soon
            an update is detected, even if outside the schedule windows.
          default: []
          selector:
            entity:
              multiple: true
              domain:
              - update
              reorder: false
        pause_entities:
          name: Pause update entities (optional)
          description: 'You can select one or more entities to pause the updates.
            If any of the selected entities is "On" or "True" the system won''t be
            updated on the schedule time.

            You can use this to hold your updates when you have a party at home, or
            when you are on vacations and don''t want to be concerned about updates
            on Home Assistant.'
          default: []
          selector:
            entity:
              multiple: true
              domain:
              - input_boolean
              - binary_sensor
              - switch
              reorder: false
    what_section:
      name: What (optional)
      icon: mdi:update
      description: Select what should be updated and what shouldn't be updated.
      collapsed: true
      input:
        core_os_update_mode:
          name: Update mode for Home Assistant core and OS updates
          description: "Please select the update mode for Home Assistant core and
            Home Assistan OS updates.\n* All: All updates will be installed.\n* Patches
            only:\n  ✅ From 2022.11.0 to 2022.11.3 will be updated (patches).\n  ❌
            From 2022.11.x to 2022.12.x will be ignored (minor update).\n  ❌ From
            2022.12.x to 2023.1.x will be ignored (major update).\n* Don't update:
            Ignore any update.\n"
          default: all
          selector:
            select:
              multiple: false
              options:
              - label: All
                value: all
              - label: Patches only
                value: patches
              - label: Don't update
                value: ignore
              sort: false
              custom_value: false
        firmware_update_mode:
          name: Update mode for device's firmware
          description: "Please select the update mode for firmware in the devices
            connected to Home Assistant (when supported as an HA update).\n* All:
            All updates will be installed.\n* Patches only:\n  ✅ From 2022.11.0 to
            2022.11.3 will be updated (patches).\n  ❌ From 2022.11.x to 2022.12.x
            will be ignored (minor update).\n  ❌ From 2022.12.x to 2023.1.x will be
            ignored (major update).\n* Don't update: Ignore any update.\n"
          default: all
          selector:
            select:
              multiple: false
              options:
              - label: All
                value: all
              - label: Patches only
                value: patches
              - label: Don't update
                value: ignore
              sort: false
              custom_value: false
        general_update_mode:
          name: Update mode for general updates
          description: "Please select the update mode for everything that is not a
            device's firmware or a core component of Home Assistant.\nThis includes
            add-ons, HACS componentes, custom cards, etc.\n* All: All updates will
            be installed.\n* Patches only:\n  ✅ From 2022.11.0 to 2022.11.3 will be
            updated (patches).\n  ❌ From 2022.11.x to 2022.12.x will be ignored (minor
            update).\n  ❌ From 2022.12.x to 2023.1.x will be ignored (major update).\n*
            Don't update: Ignore any update.\n"
          default: all
          selector:
            select:
              multiple: false
              options:
              - label: All
                value: all
              - label: Patches only
                value: patches
              - label: Don't update
                value: ignore
              sort: false
              custom_value: false
        update_exclusions:
          name: Exclusions (optional)
          description: 'Select the items that should NOT be included on the automated
            updates.


            => Use this if you want to keep some add-on on an specific version and
            avoid auto-updates to it.'
          default: []
          selector:
            entity:
              multiple: true
              domain:
              - update
              reorder: false
    backup_section:
      name: Backup (optional)
      icon: mdi:backup-restore
      description: Select the back-up options
      collapsed: true
      input:
        backup_bool:
          name: Create a full backup before start the updates?
          default: true
          selector:
            boolean: {}
        backup_wait_time:
          name: Backup wait time
          description: 'Select how long the system should wait for the backup to be
            completed after it is triggered.

            Please make sure the schedule covers the waiting time, otherwise the update
            will never be triggered after a backup.'
          default: 60
          selector:
            number:
              min: 0.0
              max: 3600.0
              step: 10.0
              mode: box
              unit_of_measurement: minutes
        max_backup_age:
          name: Maximum backup age (or zero, to disable) (optional)
          description: This requires the [Google Drive Backup](https://github.com/sabeechen/hassio-google-drive-backup)
            addon to be installed and configured to automatically backup, and provide
            a sensor with the backup states. The setting only checks for the age of
            the automatic backups from that addon, not the backups created internally
            by this blueprint.
          default:
            days: 0
            hours: 0
            minutes: 0
            seconds: 0
          selector:
            duration:
              enable_day: true
    actions_section:
      name: Actions (optional)
      icon: mdi:shoe-print
      description: Select actions to run at diferent moments on the update process
      collapsed: true
      input:
        actions_pre_update:
          name: Pre-update actions (optional)
          description: 'Actions to execute before the backup or any update starts.

            You can use this to send notifications, turn on/off devices or activate
            scenes before starting the updates.


            Note => Please be aware that all actions will run right before the update
            process, which can happens over-night. Take this in account when selecting
            your actions.

            Note => The variable "\{\{ updates_list \}\}" is available for your actions
            and contains the list of pending updates.'
          default: []
          selector:
            action: {}
        actions_pre_restart:
          name: Pre-restart actions (optional)
          description: 'Actions to execute before the automation requests a restart.

            You can use this to send notifications, turn on/off devices or stopping
            automations before restarting Home Assistant.


            Note => Please be aware that all actions will run right before the restart
            process, which can happens over-night. Take this in account when selecting
            your actions.

            Note => Note all the restarts will be controlled by this automation, like
            when a Core update is installed. These actions might not be executed in
            those cases.

            Note => The variable "\{\{ updates_list \}\}" is available for your actions
            and contains the list of pending updates.'
          default: []
          selector:
            action: {}
        actions_pos_update:
          name: Post-update actions (optional)
          description: 'Actions to execute AFTER the update process finishes.

            You can use this to send notifications, turn on/off devices or activate
            scenes after applying  the updates.


            Note => Please be aware that all actions will run right after the update
            process, which can happens over-night. Take this in account when selecting
            your actions.

            Note => The variable "\{\{ updates_list \}\}" is available for your actions
            and contains the list of pending updates.

            **IMPORTANT** => Some updates will automatically restart Home Assistant,
            causing the automation to interrupt before finishing, preventing the pos-updates
            actions to be executed. If you have critical actions to run after an update,
            consider including also in another automation based on Home Assistant
            start.

            '
          default: []
          selector:
            action: {}
    general_settings:
      name: General settings (optional)
      icon: mdi:cog
      description: Select additional settings to the update process
      collapsed: true
      input:
        restart_type:
          name: Force Home Assistant to restart if required by any update?
          description: This won't affect updates where a restart is automatic, but
            for updates requiring a manual restart (quite common on HACS) this blueprint
            can automatically force a restart by the end of the updates.
          default: no-restart
          selector:
            select:
              multiple: false
              options:
              - label: Don't force a restart
                value: no-restart
              - label: Restart Home Assistant core
                value: core
              - label: Restart Home Assistant host
                value: host
              sort: false
              custom_value: false
        verbose_logging_bool:
          name: Log addon progress with verbosity to the logbook? (optional)
          default: false
          selector:
            boolean: {}
mode: single
max_exceeded: warning
trigger_variables:
  input_update_exclusions: !input update_exclusions
  input_update_out_of_schedule: !input update_out_of_schedule
  updates_available: "{% set updates_available_obj =\n    states.update\n    | default([])\n
    \   | selectattr(\"state\", \"eq\", \"on\")\n    | rejectattr(\"entity_id\", \"in\",
    input_update_exclusions)\n%} {{\n  updates_available_obj | map(attributes=\"entity_id\")
    | list\n  if (updates_available_obj | list | count | int(0) > 0)\n  else []\n}}\n"
trigger:
- id: HA Schedule based
  platform: state
  entity_id: !input schedule_entity
- id: HA Start
  platform: homeassistant
  event: start
- id: New update
  platform: template
  value_template: "{{\n  states.update\n  | default([])\n  | selectattr(\"state\",
    \"eq\", \"on\")\n  | rejectattr(\"entity_id\", \"in\", input_update_exclusions)\n
    \ | list | count | int(0) > 0\n}}"
- id: New day
  platform: time
  at: 00:00:01
- id: Automations reloaded
  platform: event
  event_type: automation_reloaded
- id: Pause entities changed
  platform: state
  entity_id: !input pause_entities
condition:
- condition: template
  value_template: "{{\n  states.update\n  | default([])\n  | selectattr(\"state\",
    \"eq\", \"on\")\n  | rejectattr(\"entity_id\", \"in\", input_update_exclusions)\n
    \ | list | count | int(0) > 0\n}}"
- condition: or
  conditions:
  - condition: and
    conditions:
    - condition: template
      value_template: '{{ now().day >= ((input_schedule_monthday) | int(0)) }}

        '
    - condition: state
      entity_id: !input schedule_entity
      state: 'on'
  - condition: template
    value_template: "{% set ns = namespace(found=false) %} {% for item in input_update_out_of_schedule
      %}\n  {% if item in updates_available %}\n    {% set ns.found = true %}\n    {%
      break %}\n  {% endif %}\n{% endfor %} {{ ns.found }}\n"
- condition: or
  conditions:
  - '{{ input_pause_entities | default([]) | list | count | int(0) < 1 }}'
  - condition: state
    entity_id: !input pause_entities
    state: 'off'
variables:
  input_schedule_monthday: !input schedule_monthday
  input_pause_entities: !input pause_entities
  temp_input_update_exclusions: !input update_exclusions
  input_verbose_logging_bool: !input verbose_logging_bool
  input_backup_bool: !input backup_bool
  input_restart_type: !input restart_type
  temp_max_backup_age: !input max_backup_age
  input_max_backup_age_seconds: "{{\n  timedelta(\n    days=temp_max_backup_age.days,\n
    \   hours=temp_max_backup_age.hours,\n    minutes=temp_max_backup_age.minutes,\n
    \   seconds=temp_max_backup_age.seconds\n  ).total_seconds()\n}}\n"
  input_core_os_update_mode: !input core_os_update_mode
  input_firmware_update_mode: !input firmware_update_mode
  input_general_update_mode: !input general_update_mode
  updates_list: []
  pending_updates_list: []
action:
- &id001
  variables:
    core_update_entity: "{% for u in integration_entities('hassio') | select('search',
      '^update[.]')\n        if (device_attr(u, 'identifiers') | first)[1] == 'core'
      %}\n    {{ u }}\n{% endfor %}\n"
    os_update_entity: "{% for u in integration_entities('hassio') | select('search',
      '^update[.]')\n        if (device_attr(u, 'identifiers') | first)[1] == 'OS'
      %}\n    {{ u }}\n{% endfor %}\n"
    supervisor_update_entity: "{% for u in integration_entities('hassio') | select('search',
      '^update[.]')\n        if (device_attr(u, 'identifiers') | first)[1] == 'supervisor'
      %}\n    {{ u }}\n{% endfor %}\n"
    firmware_update_entities: "{{ states.update\n  | default([])\n  | selectattr('attributes.device_class',
      'defined')\n  | selectattr('attributes.device_class', 'eq', 'firmware')\n  |
      map(attribute='entity_id')\n  | list\n}}\n"
    general_update_entities: "{{ states.update\n  | default([])\n  | rejectattr('entity_id',
      'in', core_update_entity)\n  | rejectattr('entity_id', 'in', os_update_entity)\n
      \ | rejectattr('entity_id', 'in', supervisor_update_entity)\n  | rejectattr('entity_id',
      'in', firmware_update_entities)\n  | map(attribute='entity_id')\n  | list\n}}\n"
    input_update_exclusions: "{% set exclusions = temp_input_update_exclusions | default([])
      %}\n{% if input_core_os_update_mode == 'ignore' %}\n  {% set exclusions = exclusions
      + [core_update_entity | default(\"\"), os_update_entity | default(\"\")] %}\n{%
      else %}\n  {% set core_installed_version = states.update | default([]) | selectattr('entity_id',
      'in', core_update_entity | default(\"\")) | map(attribute='attributes.installed_version')
      | list | first | default('') %}\n  {% set core_latest_version = states.update
      | default([]) | selectattr('entity_id', 'in', core_update_entity | default(\"\"))
      | map(attribute='attributes.latest_version') | list | first | default('') %}\n
      \ {% set core_version_change = version(core_latest_version) - version(core_installed_version)
      %}\n  {% set os_installed_version = states.update | default([]) | selectattr('entity_id',
      'in', os_update_entity | default(\"\")) | map(attribute='attributes.installed_version')
      | list | first | default('') %}\n  {% set os_latest_version = states.update
      | default([]) | selectattr('entity_id', 'in', os_update_entity | default(\"\"))
      | map(attribute='attributes.latest_version') | list | first | default('') %}\n
      \ {% set os_version_change = version(os_latest_version) - version(os_installed_version)
      %}\n\n  {% if input_core_os_update_mode == 'patches' %}\n    {% if core_version_change.major
      or core_version_change.minor or (not core_version_change.patch) %}\n      {%
      set exclusions = exclusions + [core_update_entity | default(\"\")] %}\n    {%
      endif %}\n    {% if os_version_change.major or os_version_change.minor or (not
      os_version_change.patch) %}\n      {% set exclusions = exclusions + [os_update_entity
      | default(\"\")] %}\n    {% endif %}\n  {% elif input_core_os_update_mode ==
      'major_and_minor' %}\n    {% if (not core_version_change.major) and (not core_version_change.minor)
      %}\n      {% set exclusions = exclusions + [core_update_entity | default(\"\")]
      %}\n    {% endif %}\n    {% if (not os_version_change.major) and (not os_version_change.minor)
      %}\n      {% set exclusions = exclusions + [os_update_entity | default(\"\")]
      %}\n    {% endif %}\n  {% endif %}\n{% endif %}\n{% if input_firmware_update_mode
      == 'ignore' %}\n  {% set exclusions = exclusions + [ firmware_update_entities
      ] %}\n{% else %}\n  {% set ns = namespace(entities = []) %}\n  {% for entity
      in expand(firmware_update_entities) | rejectattr('entity_id', 'in', exclusions)
      | selectattr('state', 'eq', 'on') %}\n    {% set entity_version_change = version(entity.attributes.latest_version
      | default('')) - version(entity.attributes.installed_version | default(''))
      %}\n    {% if input_firmware_update_mode == 'patches' %}\n      {% if entity_version_change.major
      or entity_version_change.minor or (not entity_version_change.patch) %}\n        {%
      set ns.entities = ns.entities + [ entity.entity_id ] %}\n      {% endif %}\n
      \   {% elif input_firmware_update_mode == 'major_and_minor' %}\n      {% if
      (not entity_version_change.major) and (not entity_version_change.minor) %}\n
      \       {% set ns.entities = ns.entities + [ entity.entity_id ] %}\n      {%
      endif %}\n    {% endif %}\n  {% endfor %}\n  {% set exclusions = exclusions
      + [ ns.entities ] %}\n{% endif %}\n{% if input_general_update_mode == 'ignore'
      %}\n  {% set exclusions = exclusions + [ general_update_entities ] %}\n{% else
      %}\n  {% set ns = namespace(entities = []) %}\n  {% for entity in expand(general_update_entities)
      | rejectattr('entity_id', 'in', exclusions) | selectattr('state', 'eq', 'on')
      %}\n    {% set entity_version_change = version(entity.attributes.latest_version
      | default('')) - version(entity.attributes.installed_version | default(''))
      %}\n    {% if input_general_update_mode == 'patches' %}\n      {% if entity_version_change.major
      or entity_version_change.minor or (not entity_version_change.patch) %}\n        {%
      set ns.entities = ns.entities + [ entity.entity_id ] %}\n      {% endif %}\n
      \   {% elif input_general_update_mode == 'major_and_minor' %}\n      {% if (not
      entity_version_change.major) and (not entity_version_change.minor) %}\n        {%
      set ns.entities = ns.entities + [ entity.entity_id ] %}\n      {% endif %}\n
      \   {% endif %}\n  {% endfor %}\n  {% set exclusions = exclusions + [ ns.entities
      ] %}\n{% endif %}\n{{ exclusions }}\n"
    pending_updates_list: "{{ states.update\n  | default([])\n  | selectattr('state','eq','on')\n
      \ | rejectattr('entity_id', 'in', input_update_exclusions)\n  | map(attribute='entity_id')\n
      \ | list\n}}\n"
- alias: Refresh update list - update entities
  action: homeassistant.update_entity
  data: {}
  target:
    entity_id: '{{ states.update | map(attribute=''entity_id'') | list }}'
  continue_on_error: true
- variables:
    updates_list: '{{ pending_updates_list }}'
- alias: Re-check conditions
  continue_on_error: true
  if: "{{\n  (\n    states.update\n    | selectattr('state','eq','on')\n    | selectattr('entity_id',
    'in', pending_updates_list)\n    | rejectattr('entity_id', 'in', input_update_exclusions)\n
    \   | list\n    | count\n    | int(0)\n  ) < 1\n}}\n"
  then:
  - stop: Nothing to update
- &id002
  if: '{{ input_verbose_logging_bool }}'
  then:
  - alias: Logbook - variables
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      message: "Variables:\n  input_backup_bool: {{ input_backup_bool }},\n  input_restart_type:
        {{ input_restart_type }},\n  input_verbose_logging_bool: {{ input_verbose_logging_bool
        }},\n  input_max_backup_age_seconds: {{ input_max_backup_age_seconds }},\n
        \ input_schedule_monthday: {{ input_schedule_monthday }},\n  input_update_exclusions:
        {{ input_update_exclusions }},\n  input_core_os_update_mode: {{ input_core_os_update_mode
        }},\n  input_firmware_update_mode: {{ input_firmware_update_mode }},\n  input_general_update_mode:
        {{ input_general_update_mode }},\n  core_update_entity: {{ core_update_entity
        }},\n  os_update_entity: {{ os_update_entity }},\n  supervisor_update_entity:
        {{ supervisor_update_entity }},\n  firmware_update_entities: {{ firmware_update_entities
        }},\n  general_update_entities: {{ general_update_entities }},\n  updates_list:
        {{ updates_list }}"
  continue_on_error: true
- if: '{{ input_verbose_logging_bool }}'
  then:
  - alias: Logbook - A new update is available
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      domain: update
      message: A new update is available for Home Assistant.
  - alias: Logbook - List of updates
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      domain: update
      message: "List of updates: - {{ states.update\n  | selectattr('state','eq','on')\n
        \ | selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
        'in', input_update_exclusions)\n  | map(attribute='name') | list | join('\n\n-
        ') }}\n"
  - alias: 'Logbook: Running pre-update actions'
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      message: Running pre-update actions...
  continue_on_error: true
- alias: Run pre-update actions
  continue_on_error: true
  choose:
  - conditions:
    - '{{ true }}'
    sequence: !input actions_pre_update
  default: []
- alias: Check existing backups uploaded
  continue_on_error: true
  if:
  - '{{ input_max_backup_age_seconds > 0 }}'
  then:
  - variables:
      last_backup_timestamp_list: "{{\n  states.sensor\n  | selectattr(\"attributes.last_backup\",
        \"defined\")\n  | map(attribute=\"attributes.last_backup\")\n  | list\n}}\n"
      last_backup_timestamp: '{{ last_backup_timestamp_list | max if last_backup_timestamp_list
        | count > 0 else None }}'
  - alias: Check if backup state is defined
    if: '{{ last_backup_timestamp != None }}'
    then:
    - stop: Backup State sensor not found
  - alias: Check age of last uploaded backup
    if: '{{ as_timestamp(now()) - as_timestamp(last_backup_timestamp) > input_max_backup_age_seconds
      }}'
    then:
    - stop: Last uploaded backup is too old
- alias: Backup
  continue_on_error: true
  if:
  - '{{ input_backup_bool }}'
  then:
  - if: '{{ input_verbose_logging_bool }}'
    then:
    - alias: Logbook - Backing up
      continue_on_error: true
      action: logbook.log
      data:
        name: Auto-update
        entity_id: '{{ this.entity_id }}'
        message: Backing up Home Assistant.
  - alias: Call backup service
    continue_on_error: true
    action: hassio.backup_full
    data:
      compressed: true
  - if: '{{ input_verbose_logging_bool }}'
    then:
    - alias: Backup triggered
      continue_on_error: true
      action: logbook.log
      data:
        name: Auto-update
        entity_id: '{{ this.entity_id }}'
        message: Backup triggered.
    - variables:
        backup_wait_time: !input backup_wait_time
        backup_wait_time_seconds: '{{ (backup_wait_time | int(60)) * 60 }}'
    - if: '{{ backup_wait_time_seconds > 0 }}'
      then:
      - alias: Give selected wait time for the backup
        delay: '{{ backup_wait_time_seconds }}'
  else: []
- *id001
- *id002
- alias: Update - Standard
  continue_on_error: true
  repeat:
    while:
    - '{{ input_general_update_mode in [''patches'', ''major_and_minor'', ''all'']
      }}'
    - condition: state
      entity_id: !input schedule_entity
      state: 'on'
    - condition: template
      value_template: "{{ ( states.update\n  | selectattr('state','eq','on')\n  |
        selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
        'in', core_update_entity)\n  | rejectattr('entity_id', 'in', os_update_entity)\n
        \ | rejectattr('entity_id', 'in', firmware_update_entities)\n  | rejectattr('entity_id',
        'in', input_update_exclusions)\n  | map(attribute='entity_id')\n  | list |
        count | int(0) ) > 0\n}}\n"
    sequence:
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - Standard - Logbook - Starting
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Starting sequence of standard updates...
    - variables:
        pending_update_list: "{{ states.update\n  | selectattr('state','eq','on')\n
          \ | selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
          'in', core_update_entity)\n  | rejectattr('entity_id', 'in', os_update_entity)\n
          \ | rejectattr('entity_id', 'in', firmware_update_entities)\n  | rejectattr('entity_id',
          'in', input_update_exclusions)\n  | map(attribute='entity_id')\n  | list\n
          \ }}\n"
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - Standard - Logbook - Updating
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Updating {{pending_update_list[0]}} of {{pending_update_list}}
            ...
    - alias: Update - Standard - Install
      continue_on_error: true
      action: update.install
      data: {}
      target:
        entity_id: '{{ pending_update_list[0] }}'
    - alias: Update - Standard - Wait
      continue_on_error: true
      wait_template: '{{ is_state(pending_update_list[0], ''off'') }}'
      continue_on_timeout: true
      timeout: '3600'
- *id001
- *id002
- alias: Update - Core
  continue_on_error: true
  repeat:
    while:
    - '{{ input_core_os_update_mode in [''patches'', ''major_and_minor'', ''all'']
      }}'
    - condition: state
      entity_id: !input schedule_entity
      state: 'on'
    - condition: template
      value_template: "{{ ( states.update\n  | selectattr('state','eq','on')\n  |
        selectattr('entity_id', 'in', pending_updates_list)\n  | selectattr('entity_id',
        'in', core_update_entity)\n  | rejectattr('entity_id', 'in', os_update_entity)\n
        \ | rejectattr('entity_id', 'in', firmware_update_entities)\n  | rejectattr('entity_id',
        'in', input_update_exclusions)\n  | map(attribute='entity_id')\n  | list |
        count | int(0) ) > 0\n}}\n"
    sequence:
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - Core - Logbook - Starting
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Starting sequence of core items updates...
    - variables:
        pending_update_list: "{{ states.update\n  | selectattr('state','eq','on')\n
          \ | selectattr('entity_id', 'in', pending_updates_list)\n  | selectattr('entity_id',
          'in', core_update_entity)\n  | rejectattr('entity_id', 'in', os_update_entity)\n
          \ | rejectattr('entity_id', 'in', firmware_update_entities)\n  | rejectattr('entity_id',
          'in', input_update_exclusions)\n  | map(attribute='entity_id')\n  | list\n
          \ }}\n"
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - Core - Logbook - Updating
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Updating {{pending_update_list[0]}} of {{pending_update_list}}
            ...
    - alias: Update - Core - Install
      continue_on_error: true
      action: update.install
      data: {}
      target:
        entity_id: '{{ pending_update_list[0] }}'
    - alias: Update - Core - Wait
      continue_on_error: true
      wait_template: '{{ is_state(pending_update_list[0], ''off'') }}'
      continue_on_timeout: true
      timeout: '3600'
- *id001
- *id002
- alias: Update - OS
  continue_on_error: true
  repeat:
    while:
    - '{{ input_core_os_update_mode in [''patches'', ''major_and_minor'', ''all'']
      }}'
    - condition: state
      entity_id: !input schedule_entity
      state: 'on'
    - condition: template
      value_template: "{{ ( states.update\n  | selectattr('state','eq','on')\n  |
        selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
        'in', core_update_entity)\n  | selectattr('entity_id', 'in', os_update_entity)\n
        \ | rejectattr('entity_id', 'in', firmware_update_entities)\n  | rejectattr('entity_id',
        'in', input_update_exclusions)\n  | map(attribute='entity_id')\n  | list |
        count | int(0) ) > 0\n}}\n"
    sequence:
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - OS - Logbook - Starting
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Starting sequence of OS update...
    - variables:
        pending_update_list: "{{ states.update\n  | selectattr('state','eq','on')\n
          \ | selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
          'in', core_update_entity)\n  | selectattr('entity_id', 'in', os_update_entity)\n
          \ | rejectattr('entity_id', 'in', firmware_update_entities)\n  | rejectattr('entity_id',
          'in', input_update_exclusions)\n  | map(attribute='entity_id')\n  | list\n
          \ }}\n"
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - OS - Logbook - Updating
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Updating {{pending_update_list[0]}} of {{pending_update_list}}
            ...
    - alias: Update - OS - Install
      continue_on_error: true
      action: update.install
      data: {}
      target:
        entity_id: '{{ pending_update_list[0] }}'
    - alias: Update - OS - Wait
      continue_on_error: true
      wait_template: '{{ is_state(pending_update_list[0], ''off'') }}'
      continue_on_timeout: true
      timeout: '3600'
- *id001
- alias: Update - Devices firmware
  continue_on_error: true
  repeat:
    while:
    - '{{ input_firmware_update_mode in [''patches'', ''major_and_minor'', ''all'']
      }}'
    - condition: state
      entity_id: !input schedule_entity
      state: 'on'
    - condition: template
      value_template: "{{ ( states.update\n  | selectattr('state','eq','on')\n  |
        selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
        'in', core_update_entity)\n  | rejectattr('entity_id', 'in', os_update_entity)\n
        \ | selectattr('entity_id', 'in', firmware_update_entities)\n  | rejectattr('entity_id',
        'in', input_update_exclusions)\n  | map(attribute='entity_id')\n  | list |
        count | int(0) ) > 0\n}}\n"
    sequence:
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - Devices firmware - Logbook - Starting
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Starting sequence of Devices firmware update...
    - variables:
        pending_update_list: "{{ states.update\n  | selectattr('state','eq','on')\n
          \ | selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
          'in', core_update_entity)\n  | rejectattr('entity_id', 'in', os_update_entity)\n
          \ | selectattr('entity_id', 'in', firmware_update_entities)\n  | map(attribute='entity_id')\n
          \ | list\n  }}\n"
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Update - Devices firmware - Logbook - Updating
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Updating {{pending_update_list[0]}} of {{pending_update_list}}
            ...
    - alias: Update - Devices firmware - Install
      continue_on_error: true
      action: update.install
      data: {}
      target:
        entity_id: '{{ pending_update_list[0] }}'
    - alias: Update - Devices firmware - Wait
      continue_on_error: true
      wait_template: '{{ is_state(pending_update_list[0], ''off'') }}'
      continue_on_timeout: true
      timeout: '3600'
- *id001
- *id002
- if: '{{ input_verbose_logging_bool }}'
  then:
  - alias: Logbook - Updating
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      message: Finishing update process.
  - alias: Logbook - Remaining updates
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      message: "Remaining updates: - {{ states.update\n  | selectattr('state','eq','on')\n
        \ | selectattr('entity_id', 'in', pending_updates_list)\n  | rejectattr('entity_id',
        'in', input_update_exclusions)\n  | map(attribute='name') | list | join('\n\n-
        ') }}\n"
- if: '{{ input_verbose_logging_bool }}'
  then:
  - alias: Restart - Logbook
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      message: "{{ states.update\n  | selectattr('attributes.release_summary', 'defined')\n
        \ | selectattr('attributes.release_summary', 'search', \"<ha-alert alert-type='error'>\")\n
        \ | map(attribute='entity_id')\n  | list\n  | count\n  | int(0) }} item(s)
        pending a restart:\n- {{ states.update\n  | selectattr('attributes.release_summary',
        'defined')\n  | selectattr('attributes.release_summary', 'search', \"<ha-alert
        alert-type='error'>\")\n  | map(attribute='entity_id')\n  | list\n  | join('\n-
        ') }}\n"
- alias: Restart
  continue_on_error: true
  if:
  - "{{ input_restart_type != \"no-restart\" and (\n  (\n    states.update\n    |
    selectattr('attributes.release_summary', 'defined')\n    | selectattr('attributes.release_summary',
    'search', \"<ha-alert alert-type='error'>\")\n    | map(attribute='entity_id')\n
    \   | list | count | int(0)\n  ) > 0)\n}}"
  then:
  - alias: Restart - Check config
    continue_on_error: true
    action: homeassistant.check_config
  - if:
    - '{{ states.persistent_notification.invalid_config.state | default(''unavailable'')
      == ''notifying'' or states.persistent_notification.homeassistant_check_config.state
      | default(''unavailable'') == ''notifying'' }}'
    then:
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: 'Logbook: Running pre-restart actions'
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: Running pre-restart actions...
    - alias: Run pre-restart actions
      continue_on_error: true
      choose:
      - conditions:
        - '{{ true }}'
        sequence: !input actions_pre_restart
      default: []
    - if: '{{ input_verbose_logging_bool }}'
      then:
      - alias: Restart - Logbook - Skipping restart
        continue_on_error: true
        action: logbook.log
        data:
          name: Auto-update
          entity_id: '{{ this.entity_id }}'
          message: 'Skipping restart process due to notifications of invalid configurations:
            states.persistent_notification.invalid_config.state = {{ states.persistent_notification.invalid_config.state
            | default(''unavailable'') }}, states.persistent_notification.homeassistant_check_config.state
            = {{ states.persistent_notification.homeassistant_check_config.state |
            default(''unavailable'') }}

            '
    else:
    - alias: Restart - Logbook - Restarting
      continue_on_error: true
      action: logbook.log
      data:
        name: Auto-update
        entity_id: '{{ this.entity_id }}'
        message: Restarting Home Assistant {{ input_restart_type }}...
    - alias: Restart - Call reboot service
      continue_on_error: true
      action: '{{ "hassio.host_reboot" if input_restart_type == "host" else "homeassistant.restart"
        }}'
- if: '{{ input_verbose_logging_bool }}'
  then:
  - alias: Logbook - Post-actions
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      message: Running post-update actions...
- alias: Run post-update actions
  continue_on_error: true
  choose:
  - conditions:
    - '{{ true }}'
    sequence: !input actions_pos_update
  default: []
- if: '{{ input_verbose_logging_bool }}'
  then:
  - alias: Logbook - Done
    continue_on_error: true
    action: logbook.log
    data:
      name: Auto-update
      entity_id: '{{ this.entity_id }}'
      message: Done!
