Skip to content

Commit 9a07ff7

Browse files
authored
Update supervisor immediately on new version (#5375)
* Update supervisor immediately on new version * Switch reload updater task
1 parent 1a278f2 commit 9a07ff7

File tree

3 files changed

+148
-4
lines changed

3 files changed

+148
-4
lines changed

supervisor/misc/tasks.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ..coresys import CoreSysAttributes
1111
from ..exceptions import AddonsError, HomeAssistantError, ObserverError
1212
from ..homeassistant.const import LANDINGPAGE
13-
from ..jobs.decorator import Job, JobCondition
13+
from ..jobs.decorator import Job, JobCondition, JobExecutionLimit
1414
from ..plugins.const import PLUGIN_UPDATE_CONDITIONS
1515
from ..utils.dt import utcnow
1616
from ..utils.sentry import capture_exception
@@ -66,7 +66,7 @@ async def load(self):
6666

6767
# Reload
6868
self.sys_scheduler.register_task(self._reload_store, RUN_RELOAD_ADDONS)
69-
self.sys_scheduler.register_task(self.sys_updater.reload, RUN_RELOAD_UPDATER)
69+
self.sys_scheduler.register_task(self._reload_updater, RUN_RELOAD_UPDATER)
7070
self.sys_scheduler.register_task(self.sys_backups.reload, RUN_RELOAD_BACKUPS)
7171
self.sys_scheduler.register_task(self.sys_host.reload, RUN_RELOAD_HOST)
7272
self.sys_scheduler.register_task(self.sys_ingress.reload, RUN_RELOAD_INGRESS)
@@ -136,6 +136,7 @@ async def _update_addons(self):
136136
JobCondition.INTERNET_HOST,
137137
JobCondition.RUNNING,
138138
],
139+
limit=JobExecutionLimit.ONCE,
139140
)
140141
async def _update_supervisor(self):
141142
"""Check and run update of Supervisor Supervisor."""
@@ -333,3 +334,12 @@ async def _watchdog_addon_application(self):
333334
async def _reload_store(self) -> None:
334335
"""Reload store and check for addon updates."""
335336
await self.sys_store.reload()
337+
338+
@Job(name="tasks_reload_updater")
339+
async def _reload_updater(self) -> None:
340+
"""Check for new versions of Home Assistant, Supervisor, OS, etc."""
341+
await self.sys_updater.reload()
342+
343+
# If there's a new version of supervisor, start update immediately
344+
if self.sys_supervisor.need_update:
345+
await self._update_supervisor()

tests/fixtures/version_stable.json

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{
2+
"channel": "stable",
3+
"supervisor": "2024.10.0",
4+
"homeassistant": {
5+
"default": "2024.10.4",
6+
"qemux86": "2024.10.4",
7+
"qemux86-64": "2024.10.4",
8+
"qemuarm": "2024.10.4",
9+
"qemuarm-64": "2024.10.4",
10+
"generic-x86-64": "2024.10.4",
11+
"intel-nuc": "2024.10.4",
12+
"khadas-vim3": "2024.10.4",
13+
"raspberrypi": "2024.10.4",
14+
"raspberrypi2": "2024.10.4",
15+
"raspberrypi3": "2024.10.4",
16+
"raspberrypi3-64": "2024.10.4",
17+
"raspberrypi4": "2024.10.4",
18+
"raspberrypi4-64": "2024.10.4",
19+
"raspberrypi5-64": "2024.10.4",
20+
"yellow": "2024.10.4",
21+
"green": "2024.10.4",
22+
"tinker": "2024.10.4",
23+
"odroid-c2": "2024.10.4",
24+
"odroid-c4": "2024.10.4",
25+
"odroid-m1": "2024.10.4",
26+
"odroid-n2": "2024.10.4",
27+
"odroid-xu": "2024.10.4"
28+
},
29+
"hassos": {
30+
"ova": "13.2",
31+
"rpi2": "13.2",
32+
"rpi3": "13.2",
33+
"rpi3-64": "13.2",
34+
"rpi4": "13.2",
35+
"rpi4-64": "13.2",
36+
"rpi5-64": "13.2",
37+
"yellow": "13.2",
38+
"green": "13.2",
39+
"tinker": "13.2",
40+
"odroid-c2": "13.2",
41+
"odroid-c4": "13.2",
42+
"odroid-m1": "13.2",
43+
"odroid-m1s": "13.2",
44+
"odroid-n2": "13.2",
45+
"odroid-xu4": "13.2",
46+
"generic-x86-64": "13.2",
47+
"generic-aarch64": "13.2",
48+
"khadas-vim3": "13.2"
49+
},
50+
"hassos-upgrade": {
51+
"11": "11.5",
52+
"10": "10.5",
53+
"9": "9.5",
54+
"8": "8.5",
55+
"7": "7.6",
56+
"6": "6.6",
57+
"5": "5.13",
58+
"4": "4.20",
59+
"3": "3.13"
60+
},
61+
"ota": "https://os-artifacts.home-assistant.io/{version}/{os_name}_{board}-{version}.raucb",
62+
"cli": "2024.09.0",
63+
"dns": "2024.04.0",
64+
"audio": "2023.12.0",
65+
"multicast": "2024.03.0",
66+
"observer": "2023.06.0",
67+
"image": {
68+
"core": "homeassistant/{machine}-homeassistant",
69+
"supervisor": "homeassistant/{arch}-hassio-supervisor",
70+
"cli": "homeassistant/{arch}-hassio-cli",
71+
"audio": "homeassistant/{arch}-hassio-audio",
72+
"dns": "homeassistant/{arch}-hassio-dns",
73+
"observer": "homeassistant/{arch}-hassio-observer",
74+
"multicast": "homeassistant/{arch}-hassio-multicast"
75+
},
76+
"images": {
77+
"core": "ghcr.io/home-assistant/{machine}-homeassistant",
78+
"supervisor": "ghcr.io/home-assistant/{arch}-hassio-supervisor",
79+
"cli": "ghcr.io/home-assistant/{arch}-hassio-cli",
80+
"audio": "ghcr.io/home-assistant/{arch}-hassio-audio",
81+
"dns": "ghcr.io/home-assistant/{arch}-hassio-dns",
82+
"observer": "ghcr.io/home-assistant/{arch}-hassio-observer",
83+
"multicast": "ghcr.io/home-assistant/{arch}-hassio-multicast"
84+
}
85+
}

tests/misc/test_tasks.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
11
"""Test scheduled tasks."""
22

3-
from unittest.mock import MagicMock, Mock, patch
3+
from collections.abc import AsyncGenerator
4+
from contextlib import asynccontextmanager
5+
from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, patch
46

57
from awesomeversion import AwesomeVersion
68
import pytest
79

10+
from supervisor.const import CoreState
811
from supervisor.coresys import CoreSys
912
from supervisor.exceptions import HomeAssistantError
1013
from supervisor.homeassistant.api import HomeAssistantAPI
1114
from supervisor.homeassistant.const import LANDINGPAGE
1215
from supervisor.homeassistant.core import HomeAssistantCore
1316
from supervisor.misc.tasks import Tasks
17+
from supervisor.supervisor import Supervisor
18+
19+
from tests.common import load_fixture
1420

1521
# pylint: disable=protected-access
1622

1723

1824
@pytest.fixture(name="tasks")
19-
async def fixture_tasks(coresys: CoreSys, container: MagicMock) -> Tasks:
25+
async def fixture_tasks(
26+
coresys: CoreSys, container: MagicMock
27+
) -> AsyncGenerator[Tasks]:
2028
"""Return task manager."""
2129
coresys.homeassistant.watchdog = True
2230
coresys.homeassistant.version = AwesomeVersion("2023.12.0")
@@ -159,3 +167,44 @@ async def test_watchdog_homeassistant_api_reanimation_limit(
159167
assert not caplog.text
160168
restart.assert_not_called()
161169
rebuild.assert_not_called()
170+
171+
172+
async def test_reload_updater_triggers_supervisor_update(
173+
tasks: Tasks, coresys: CoreSys
174+
):
175+
"""Test an updater reload triggers a supervisor update if there is one."""
176+
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
177+
coresys.core.state = CoreState.RUNNING
178+
coresys.security.content_trust = False
179+
180+
version_data = load_fixture("version_stable.json")
181+
version_resp = AsyncMock()
182+
version_resp.status = 200
183+
version_resp.read.return_value = version_data
184+
185+
@asynccontextmanager
186+
async def mock_get_for_version(*args, **kwargs) -> AsyncGenerator[AsyncMock]:
187+
"""Mock get call for version information."""
188+
yield version_resp
189+
190+
with (
191+
patch("supervisor.coresys.aiohttp.ClientSession.get", new=mock_get_for_version),
192+
patch.object(
193+
Supervisor,
194+
"version",
195+
new=PropertyMock(return_value=AwesomeVersion("2024.10.0")),
196+
),
197+
patch.object(Supervisor, "update") as update,
198+
):
199+
# Set supervisor's version intially
200+
await coresys.updater.reload()
201+
assert coresys.supervisor.latest_version == AwesomeVersion("2024.10.0")
202+
203+
# No change in version means no update
204+
await tasks._reload_updater()
205+
update.assert_not_called()
206+
207+
# Version change causes an update
208+
version_resp.read.return_value = version_data.replace("2024.10.0", "2024.10.1")
209+
await tasks._reload_updater()
210+
update.assert_called_once()

0 commit comments

Comments
 (0)