Automating software upgrades

Posted on May 1, 2022

I’m a big fan of Homeassistant, and have been using it since its early stages. The cool thing with it, is that you can do about anything that you need to base on events (it is basically an event machine). Keeping up to date on software relases, can be a chore. So why not try to automate it?

Here’s how I upgrade some package releases automatically using Homeassistant with a shell command and an ansible playbook.

First I define a sensor, using the rest integration to pull the release version from github (github login required) :

- platform: rest
  name: element web release
  resource: https://api.github.com/repos/vector-im/element-web/releases/latest
  scan_interval: 7200
  value_template: '{{ value_json.tag_name }}'
  username: !secret github_username
  password: !secret github_access_token
  authentication: basic
  headers:
    Accept: application/vnd.github.v3+json
    Content-Type: application/json
    User-Agent: Home Assistant REST sensor

The automation will trigger on any state change in the sensor, and call the ansible playbook (assuming a predefined boolean switch ‘automatic_updates’ is switched on), and notify a notification platform of any changes:

alias: "upgrade elements on new version"

trigger:
  - platform: state
    entity_id: sensor.elements_release

variables:
  playbook: 'upgrade_elements.yml'

condition:
  condition: state
  entity_id: input_boolean.automatic_updates
  state: "on"

action:
  - service: shell_command.run_playbook
    data_template:
      playbook: "{{ playbook }}"
      release: "{{ trigger.to_state.state }}

  - service: notify.notify
    data:
      title: "Upgrade notification"
      message: "Running playbook {{ playbook }} New state: {{ trigger.to_state.state }}"

.. Below is the command script which actually executes the ansible playbook. (note: I use fish as my shell). Since Ansible runs on another server, you need to setup password-less login with ssh keys.

#!/usr/bin/fish
set -l playbook $argv[1]
set -l args $argv[2..-1]

if test -z $playbook
   exit 0
end

ssh -i /config/.ssh/id_rsa.pub user@server "cd /data/ansible; ansible-playbook $playbook $args"

And here’s my Ansible playbook for this one (only showing the playbook):


- hosts: <your host>

  vars:
    release: ""            
    version: "v1.8.2""            
    target_dir: "/var/www/html"

  gather_facts: no
  become: true

    - name: Download release version
      get_url:
        url: https://github.com/vector-im/element-web/releases/download/{{ version }}/element-{{ version }}.tar.gz
        dest: /tmp
      tags: 
        - download

    - name: unarchive
      unarchive: 
        src: "/tmp/element-{{version }}.tar.gz"
        dest: /var/www/html
        remote_src: yes
        creates: "{{ target_dir }}/element-{{ version }}"
      tags: 
        - unarchive

    - name: Copy config file
      copy: 
        src: "{{ target_dir }}/element/config.json"
        dest: "{{ target_dir }}/element-{{ version }}"
        remote_src: yes      
      tags:
       - config

    - name: unlink
      file:
        src: "{{ target_dir }}/element-{{ version }}" 
        dest: "{{ target_dir }}/element"
        state: link
        force: yes

This is just one example, but you can add more triggers, to get more packages upgraded in the same automation, with more custom playbooks.

Best,

=Jinxd=