{% extends "admin/_layout.html" %} {% from "_macros.html" import icon %} {% set section = "updates" %} {% block title %}Updates - {{ brand.name }}{% endblock %} {% block heading %}Updates{% endblock %} {% block admin_content %}

What is running here, what is on {{ state.branch }}, and what changed between. Checking reaches the remote; opening this page does not.

{% if saved %}
{{ icon("check", "icon--sm") }} {{ saved }}
{% endif %} {% if state.error %}
{{ icon("warning", "icon--sm") }} {{ state.error }}
{% endif %}

Running

Version
{{ state.version }}
{% if state.head %}
Commit
{{ state.head.short }} {{ state.head.subject }} {% if state.dirty %} uncommitted changes {% endif %}
{% endif %} {% if state.checkout %}
Checkout
{{ state.checkout }}
{% endif %}
{% if not state.is_git %}

This was not installed from a git checkout — a container image, or a wheel — so there is nothing here to compare or update. Update the image instead.

{% else %}
{% endif %}
{% if state.is_git %}

Available {% if state.up_to_date %}up to date {% elif state.behind %}{{ state.behind | length }} behind {% endif %}

{% if not state.remote %}

Nothing known about origin/{{ state.branch }} yet. Check the remote above.

{% elif state.up_to_date %}

{{ state.remote.short }} is what is running.

{% else %}

{{ state.remote.short }} {{ state.remote.subject }}

{# The log between, not just a count. "3 behind" is a number somebody has to go and look up; the subjects are the thing that decides whether this is worth restarting for right now. #} {% if state.dirty %}
{{ icon("warning", "icon--sm") }} This checkout has uncommitted changes. The update does a hard reset, which would throw them away — nothing here is meant to be edited in place, so this usually means somebody was debugging on the box.
{% endif %} {% endif %}
{# Its own card, and rendered whether or not there is anything to apply. It used to live inside the "there is an update" branch, so an administrator could not find out that the helper was missing until the day they needed it -- which is the worst moment to discover a thing has to be installed from a shell. #}

Applying an update

{% if state.requested %}
{{ icon("clock", "icon--sm") }} An update has been requested and is waiting for the helper to pick it up. The service restarts when it does.
{% elif state.helper %}

This host has the update helper installed, so the button below writes a request that a systemd unit picks up and runs as root. It always deploys {{ state.branch }} — the request carries no branch and no ref, so pressing it is never “deploy something else”.

Every restart ends every open terminal session — a command still running on the far side is cut off. A reply being written is saved with whatever it has.

{% else %}
{{ icon("shield", "icon--sm") }} The update helper is not installed on this host, so there is no button. That is the honest default: the service runs as an unprivileged account and cannot restart itself, and a web application that can is one whose worst day is much worse. Run this instead: {{ command }}

To install it, re-run the installer with INSTALL_UPDATE_HELPER=1. Doing so means anybody who can administer this web interface can deploy whatever is on {{ state.branch }} — which is the point, and worth deciding on purpose rather than arriving at.

{% endif %}
{% endif %} {% endblock %}