Stop refreshing the update information on outdated OS versions#6098
Stop refreshing the update information on outdated OS versions#6098
Conversation
|
With this change, on an unsupported Home Assistant OS, Supervisor stops updating the version information. The logs will have the following messages: |
4c9478c to
32f17ad
Compare
There was a problem hiding this comment.
There is something a bit odd about this. The primary difference between Unsupported and Unhealthy is that Unhealthy blocks updates. So why not just change UnsupportedReason.OS_VERSION to UnhealthyReason.OS_VERSION?
This feels more right though. The system isn't actually unhealthy, its just moved to unsupported because its been too long since it was updated. Even if it is more work for us to make this one unsupported reason work like this 😆
supervisor/os/manager.py
Outdated
| self._os_name = cpe.get_product()[0] | ||
|
|
||
| # Evaluate OS version early to make OS_SUPPORTED Job condition work | ||
| await self.sys_resolution.evaluate.get("os_version")() |
There was a problem hiding this comment.
I'm not a fan of this. I get why you're doing it but besides creating this odd dependency on resolution center here, its actually running this before ResolutionManager loads. We get away with it today because ResolutionManager load doesn't really do much, just runs a healthcheck and schedules future ones. Any future change made assuming ResolutionManager was loaded before any of its functionality was used (a reasonable assumption) would cause this to break...
What if we made updater check if already has a version file and if so it delays the fetch? Either until the next time the task runs or schedule it to run when we transition to CoreState.STARTUP.
Seems like that would solve two problems. We could remove this special check and just let the normal SETUP healthcheck handle it. And if we don't have a version file then we fetch latest before checking if the OS is unsupported. Because having the latest version info is better then having nothing at all.
There was a problem hiding this comment.
What if we made updater check if already has a version file and if so it delays the fetch? Either until the next time the task runs or schedule it to run when we transition to
CoreState.STARTUP.
Uh yes, I like that idea! We already delay in case there is no connectivity, so it is not uncommon that we have to delay (altough, I now wonder what happens if there is no version file and no connectivity, is that case handled somewhat gracefully today 🤔 ).
There was a problem hiding this comment.
I think if we have no information on what the latest version is we assume whatever version of HAOS your on is supported right? So I guess the second problem wasn't actually an issue since the fetch wouldn't be blocked if you had no current version file. But it still lets us drop the unexpected dependency which seems like enough of a plus.
There was a problem hiding this comment.
With this, Supervisor now only updates when there are really no update information available, e.g.
2025-08-20 12:04:34.486 INFO (MainThread) [supervisor.updater] No OS update information found, force refreshing updater information
2025-08-20 12:04:34.486 INFO (MainThread) [supervisor.updater] Fetching update data from https://version.home-assistant.io/stable.json
Similar when plug-ins need update information.
Add `JobCondition.OS_SUPPORTED` to the updater job to avoid refreshing update information when the OS version is unsupported. This effectively freezes installations on unsupported OS versions and blocks Supervisor updates. Once deployed, this ensures that any Supervisor will always run on at least the minimum supported OS version. This requires to move the OS version check before Supervisor updater initialization to allow the `JobCondition.OS_SUPPORTED` to work correctly.
Instead of running a full system evaluation, only run the OS version check right after the OS manager is loaded. This allows the updater job condition to work correctly without running the full system evaluation, which is not needed at this point.
Also prevent Home Assistant Core and Add-on updates on unsupported OS versions. We could imply `JobCondition.SUPERVISOR_UPDATED` whenever OS is outdated, but this would also prevent the OS update itself. So we need this separate condition everywhere where `JobCondition.SUPERVISOR_UPDATED` is used except for OS updates. It should also be safe to let the add-on store update, we simply don't allow the add-on to be installed or updated if the OS is outdated.
It seems that the CPE information are already loaded in the HostInfo object. Remove the unnecessary update call.
Delay refreshing of update data until after setup phase. This allows to use the JobCondition.OS_SUPPORTED safely. We still have to fetch the updater data in case OS information is outdated. This typically happens on device wipe. Note also that plug-ins will automatically refresh updater data in case it is missing the latest version information. This will reverse the order of updates when there are new plug-in and Supervisor update information available (e.g. on first startup): Previously the updater data got refreshed before the plug-in started, which caused them to update first. Then the Supervisor got update in startup phase. Now the updater data gets refreshed in startup phase, which then causes the Supervisor to update first before the plug-ins get updated after Supervisor restart.
9e3fc39 to
1bfd617
Compare
| # If there's no connectivity, delay initial version fetch | ||
| if not self.sys_supervisor.connectivity: | ||
| if not self._connectivity_listener: | ||
| self._connectivity_listener = self.sys_bus.register_event( | ||
| BusEvent.SUPERVISOR_CONNECTIVITY_CHANGE, self._check_connectivity | ||
| ) | ||
| _LOGGER.info("No Supervisor connectivity, delaying version fetch") | ||
| return | ||
|
|
There was a problem hiding this comment.
So when this code was in load it would only delay the initial version fetch since load was only called once.
Now that this code is in reload it will happen repeatedly. We call reload on a schedule from a task. Any time that is called and the internet is down it will delay that until the internet comes back up. Whereas in the past it would've simply skipped that call to reload and tried again next time.
I think its ok like this but wanted to clarify the new behavior. Because this is a change in behavior, that comment is a little misleading. It's not just the initial fetch that can get delayed anymore, its all of them.
There was a problem hiding this comment.
Right, but since we have JobCondition.SUPERVISOR_INTERNET anyways, it won't get actually called. So this essentially gets rid of some warnings:
[supervisor.jobs] 'Updater.fetch_data' blocked from execution, no supervisor internet connection
Given that this was a warning before, maybe we should at least print a debug log message 🤔
From a behavior standpoint it should just lead to updates fetched as soon as we regain Internet connection. It should end up calling fetch_data not less then before.
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
Proposed change
Add
JobCondition.OS_SUPPORTEDto the updater job to avoid refreshing update information when the OS version is unsupported.This effectively freezes installations on unsupported OS versions and blocks Supervisor updates. Once deployed, this pretty much guarantees that any current Supervisor version will always run on at least the minimum supported OS version (except if the user manually intervenes, like deleting the updater file). This allows to drop compatibility code safely.
This requires to move the OS version check before Supervisor updater initialization to allow the
JobCondition.OS_SUPPORTEDto work correctly.Type of change
Additional information
Checklist
ruff format supervisor tests)If API endpoints or add-on configuration are added/changed: