mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-13 10:36:35 +00:00
fix(auto-update): CI failures on Linux
- Keep the setup result when chown fails. CI runs as a non-root user, where chown to the web user raises; that discarded the result file, so the General tab would never learn whether setup worked. Regression test added. - Register the two new /api/v3/system/auto-update routes in the URL map snapshot. - Use utility classes app.css defines (space-y-1, hover:text-red-600). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -195,7 +195,12 @@ class UpdateHelperSetup:
|
|||||||
json.dump(result, f, indent=2)
|
json.dump(result, f, indent=2)
|
||||||
os.chmod(tmp, 0o644)
|
os.chmod(tmp, 0o644)
|
||||||
if self._web_ids and hasattr(os, 'chown'):
|
if self._web_ids and hasattr(os, 'chown'):
|
||||||
os.chown(tmp, *self._web_ids)
|
# Only root can give the file away; the result is readable
|
||||||
|
# (0644) either way, so a failed chown must not lose it.
|
||||||
|
try:
|
||||||
|
os.chown(tmp, *self._web_ids)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
os.replace(tmp, self.result_file)
|
os.replace(tmp, self.result_file)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
logger.warning("Could not record automatic update setup result: %s", e)
|
logger.warning("Could not record automatic update setup result: %s", e)
|
||||||
|
|||||||
Vendored
+17
@@ -841,6 +841,23 @@
|
|||||||
"POST"
|
"POST"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"/api/v3/system/auto-update",
|
||||||
|
"api_v3.get_auto_update_status",
|
||||||
|
[
|
||||||
|
"GET",
|
||||||
|
"HEAD",
|
||||||
|
"OPTIONS"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/api/v3/system/auto-update/dismiss",
|
||||||
|
"api_v3.dismiss_auto_update_alert",
|
||||||
|
[
|
||||||
|
"OPTIONS",
|
||||||
|
"POST"
|
||||||
|
]
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"/api/v3/system/check-update",
|
"/api/v3/system/check-update",
|
||||||
"api_v3.check_for_update",
|
"api_v3.check_for_update",
|
||||||
|
|||||||
@@ -167,3 +167,16 @@ def test_not_a_systemd_host_is_left_alone(tmp_path):
|
|||||||
systemctl = FakeSystemctl()
|
systemctl = FakeSystemctl()
|
||||||
assert setup(root, tmp_path / 'no-etc', systemctl).ensure(ON) is None
|
assert setup(root, tmp_path / 'no-etc', systemctl).ensure(ON) is None
|
||||||
assert systemctl.calls == []
|
assert systemctl.calls == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_result_is_kept_when_it_cannot_be_given_to_the_web_user(tmp_path, monkeypatch):
|
||||||
|
"""Caught by CI, which runs as a non-root Linux user: chown needs root, and
|
||||||
|
a failed chown used to discard the result, so the General tab never
|
||||||
|
learned whether setup worked."""
|
||||||
|
def refuse(*args):
|
||||||
|
raise PermissionError('Operation not permitted')
|
||||||
|
monkeypatch.setattr(aus.os, 'chown', refuse, raising=False)
|
||||||
|
root, etc = project(tmp_path)
|
||||||
|
out = setup(root, etc, FakeSystemctl()).ensure(ON)
|
||||||
|
assert out['status'] == 'installed'
|
||||||
|
assert result(root) == out
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
<p class="mt-1 ml-6 text-xs text-blue-700">An update was just installed and its health check is running.</p>
|
<p class="mt-1 ml-6 text-xs text-blue-700">An update was just installed and its health check is running.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if auto_update_status and (auto_update_status.last_run or auto_update_status.next_due) %}
|
{% if auto_update_status and (auto_update_status.last_run or auto_update_status.next_due) %}
|
||||||
<div class="mt-1 ml-6 text-xs text-gray-500 space-y-0.5">
|
<div class="mt-1 ml-6 text-xs text-gray-500 space-y-1">
|
||||||
{% if auto_update_status.last_run %}
|
{% if auto_update_status.last_run %}
|
||||||
<p>Last automatic update: {{ auto_update_status.last_run }}
|
<p>Last automatic update: {{ auto_update_status.last_run }}
|
||||||
<span class="{{ 'text-red-600' if auto_update_status.status == 'error' else '' }}">— {{ auto_update_status.summary }}</span></p>
|
<span class="{{ 'text-red-600' if auto_update_status.status == 'error' else '' }}">— {{ auto_update_status.summary }}</span></p>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<p class="text-sm text-red-700 mt-1" id="auto-update-banner-text"></p>
|
<p class="text-sm text-red-700 mt-1" id="auto-update-banner-text"></p>
|
||||||
<p class="text-xs text-red-600 mt-1">Details are under Automatic Updates on the General tab.</p>
|
<p class="text-xs text-red-600 mt-1">Details are under Automatic Updates on the General tab.</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" onclick="window.dismissAutoUpdateBanner()" class="ml-4 flex-shrink-0 text-red-500 hover:text-red-700" aria-label="Dismiss">
|
<button type="button" onclick="window.dismissAutoUpdateBanner()" class="ml-4 flex-shrink-0 text-red-500 hover:text-red-600" aria-label="Dismiss">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user