feat: add controller update trigger + version checker (v0.1.8)

Hub now tracks controller_url from reports, periodically checks the Gitea
registry for the latest controller image version, and shows a "Trigger Update"
button on the customer detail page that proxies to the controller's self-update
API endpoint using the shared API key.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 18:16:38 +01:00
parent d8e1ec44d7
commit 36a7d1c162
6 changed files with 444 additions and 35 deletions
+79
View File
@@ -183,6 +183,85 @@
{{end}}
</section>
<!-- Controller Update -->
<section class="card">
<h2>Controller Update</h2>
<div class="info-grid">
<div class="info-item">
<span class="label">Current version</span>
<span class="value">v{{.Customer.ControllerVersion}}</span>
</div>
{{if .LatestVersion}}
<div class="info-item">
<span class="label">Latest version</span>
<span class="value">
v{{.LatestVersion}}
{{if .UpdateAvailable}}
<span style="color: #4ade80; margin-left: 0.3em;">● update available</span>
{{else}}
<span style="color: #94a3b8; margin-left: 0.3em;">— up to date</span>
{{end}}
</span>
</div>
{{end}}
{{if .ControllerURL}}
<div class="info-item">
<span class="label">Controller URL</span>
<span class="value"><a href="{{.ControllerURL}}" target="_blank" style="color: #60a5fa;">{{.ControllerURL}}</a></span>
</div>
{{end}}
</div>
{{if and .ControllerURL .UpdateAvailable}}
<div style="margin-top: 0.75em;">
<button class="btn" id="btn-trigger-update" onclick="triggerControllerUpdate('{{.Customer.CustomerID}}')">
Trigger Update
</button>
<span id="update-msg" style="margin-left: 0.5em; display: none;"></span>
</div>
{{else if and .ControllerURL (not .LatestVersion)}}
<div style="margin-top: 0.75em;">
<button class="btn" id="btn-trigger-update" onclick="triggerControllerUpdate('{{.Customer.CustomerID}}')">
Trigger Update
</button>
<span id="update-msg" style="margin-left: 0.5em; display: none;"></span>
<p style="color: #94a3b8; font-size: 0.85em; margin-top: 0.3em;">Registry check not configured — cannot verify if update is available</p>
</div>
{{end}}
</section>
<script>
function triggerControllerUpdate(customerID) {
if (!confirm('Trigger self-update on this controller?\n\nThe controller will be briefly unavailable during restart.')) return;
var btn = document.getElementById('btn-trigger-update');
var msg = document.getElementById('update-msg');
btn.disabled = true;
btn.textContent = 'Triggering...';
msg.style.display = 'none';
fetch('/customers/' + customerID + '/trigger-update', {method: 'POST'})
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.ok) {
msg.textContent = 'Update triggered — controller restarting';
msg.style.display = 'inline';
msg.style.color = '#4ade80';
} else {
msg.textContent = data.error || 'Failed';
msg.style.display = 'inline';
msg.style.color = '#f87171';
btn.disabled = false;
btn.textContent = 'Trigger Update';
}
})
.catch(function() {
msg.textContent = 'Connection error';
msg.style.display = 'inline';
msg.style.color = '#f87171';
btn.disabled = false;
btn.textContent = 'Trigger Update';
});
}
</script>
<!-- Notifications -->
<section class="card">
<h2>Notifications</h2>