1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-04-18 07:35:22 +01:00
Commit Graph

5584 Commits

Author SHA1 Message Date
dependabot[bot]
f7e3ca8f44 Bump astroid from 4.0.3 to 4.1.2
Bumps [astroid](https://github.com/pylint-dev/astroid) from 4.0.3 to 4.1.2.
- [Release notes](https://github.com/pylint-dev/astroid/releases)
- [Changelog](https://github.com/pylint-dev/astroid/blob/main/ChangeLog)
- [Commits](https://github.com/pylint-dev/astroid/compare/v4.0.3...v4.1.2)

---
updated-dependencies:
- dependency-name: astroid
  dependency-version: 4.1.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-13 08:38:07 +00:00
dependabot[bot]
e7531463e6 Bump mypy from 1.20.0 to 1.20.1 (#6728)
Bumps [mypy](https://github.com/python/mypy) from 1.20.0 to 1.20.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.20.0...v1.20.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-version: 1.20.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 10:36:47 +02:00
dependabot[bot]
eb25fc4b40 Bump actions/upload-artifact from 7.0.0 to 7.0.1 (#6727)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](bbbca2ddaa...043fb46d1a)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 09:07:01 +02:00
Stefan Agner
28fa0b35bd Use Unix socket for Supervisor to Core communication (#6590)
* Use Unix socket for Supervisor to Core communication

Switch internal Supervisor-to-Core HTTP and WebSocket communication
from TCP (port 8123) to a Unix domain socket.

The existing /run/supervisor directory on the host (already mounted
at /run/os inside the Supervisor container) is bind-mounted into the
Core container at /run/supervisor. Core receives the socket path via
the SUPERVISOR_CORE_API_SOCKET environment variable, creates the
socket there, and Supervisor connects to it via aiohttp.UnixConnector
at /run/os/core.sock.

Since the Unix socket is only reachable by processes on the same host,
requests arriving over it are implicitly trusted and authenticated as
the existing Supervisor system user. This removes the token round-trip
where Supervisor had to obtain and send Bearer tokens on every Core
API call. WebSocket connections are likewise authenticated implicitly,
skipping the auth_required/auth handshake.

Key design decisions:
- Version-gated by CORE_UNIX_SOCKET_MIN_VERSION so older Core
  versions transparently continue using TCP with token auth
- LANDINGPAGE is explicitly excluded (not a CalVer version)
- Hard-fails with a clear error if the socket file is unexpectedly
  missing when Unix socket communication is expected
- WSClient.connect() for Unix socket (no auth) and
  WSClient.connect_with_auth() for TCP (token auth) separate the
  two connection modes cleanly
- Token refresh always uses the TCP websession since it is inherently
  a TCP/Bearer-auth operation
- Logs which transport (Unix socket vs TCP) is being used on first
  request

Closes #6626
Related Core PR: home-assistant/core#163907

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Close WebSocket on handshake failure and validate auth_required

Ensure the underlying WebSocket connection is closed before raising
when the handshake produces an unexpected message. Also validate that
the first TCP message is auth_required before sending credentials.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix pylint protected-access warnings in tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Check running container env before using Unix socket

Split use_unix_socket into two properties to handle the Supervisor
upgrade transition where Core is still running with a container
started by the old Supervisor (without SUPERVISOR_CORE_API_SOCKET):

- supports_unix_socket: version check only, used when creating the
  Core container to decide whether to set the env var
- use_unix_socket: version check + running container env check, used
  for communication decisions

This ensures TCP fallback during the upgrade transition while still
hard-failing if the socket is missing after Supervisor configured
Core to use it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Improve Core API communication logging and error handling

- Remove transport log from make_request that logged before Core
  container was attached, causing misleading connection logs
- Log "Connected to Core via ..." once on first successful API response
  in get_api_state, when the transport is actually known
- Remove explicit socket existence check from session property, let
  aiohttp UnixConnector produce natural connection errors during
  Core startup (same as TCP connection refused)
- Add validation in get_core_state matching get_config pattern
- Restore make_request docstring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Guard Core API requests with container running check

Add is_running() check to make_request and connect_websocket so no
HTTP or WebSocket connection is attempted when the Core container is
not running. This avoids misleading connection attempts during
Supervisor startup before Core is ready.

Also make use_unix_socket raise if container metadata is not available
instead of silently falling back to TCP. This is a defensive check
since is_running() guards should prevent reaching this state.

Add attached property to DockerInterface to expose whether container
metadata has been loaded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Reset Core API connection state on container stop

Listen for Core container STOPPED/FAILED events to reset the
connection state: clear the _core_connected flag so the transport
is logged again on next successful connection, and close any stale
Unix socket session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Only mount /run/supervisor if we use it

* Fix pytest errors

* Remove redundant is_running check from ingress panel update

The is_running() guard in update_hass_panel is now redundant since
make_request checks is_running() internally. Also mock is_running
in the websession test fixture since tests using it need make_request
to proceed past the container running check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Bind mount /run/supervisor to Supervisor /run/os

Home Assistant OS (as well as the Supervised run scripts) bind mount
/run/supervisor to /run/os in Supervisor. Since we reuse this location
for the communication socket between Supervisor and Core, we need to
also bind mount /run/supervisor to Supervisor /run/os in CI.

* Wrap WebSocket handshake errors in HomeAssistantAPIError

Unexpected exceptions during the WebSocket handshake (KeyError,
ValueError, TypeError from malformed messages) are now wrapped in
HomeAssistantAPIError inside WSClient.connect/connect_with_auth.
This means callers only need to catch HomeAssistantAPIError.

Remove the now-unnecessary except (RuntimeError, ValueError,
TypeError) from proxy _websocket_client and add a proper error
message to the APIError per review feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Narrow WebSocket handshake exception handling

Replace broad `except Exception` with specific exception types that
can actually occur during the WebSocket handshake: KeyError (missing
dict keys), ValueError (bad JSON), TypeError (non-text WS message),
aiohttp.ClientError (connection errors), and TimeoutError. This
avoids silently wrapping programming errors into HomeAssistantAPIError.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove unused create_mountpoint from MountBindOptions

The field was added but never used. The /run/supervisor host path
is guaranteed to exist since HAOS creates it for the Supervisor
container mount, so auto-creating the mountpoint is unnecessary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Clear stale access token before raising on final retry

Move token clear before the attempt check in connect_websocket so
the stale token is always discarded, even when raising on the final
attempt. Without this, the next call would reuse the cached bad token
via _ensure_access_token's fast path, wasting a round-trip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add tests for Unix socket communication and Core API

Add tests for the new Unix socket communication path and improve
existing test coverage:

- Version-based supports_unix_socket and env-based use_unix_socket
- api_url/ws_url transport selection
- Connection lifecycle: connected log after restart, ignoring
  unrelated container events
- get_api_state/check_api_state parameterized across versions,
  responses, and error cases
- make_request is_running guard and TCP flow with real token fetch
- connect_websocket for both Unix and TCP (with token verification)
- WSClient.connect/connect_with_auth handshake success, errors,
  cleanup on failure, and close with pending futures

Consolidate existing tests into parameterized form and drop synthetic
tests that covered very little.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:09:38 +02:00
Stefan Agner
5de5d594a5 Clean up old apps builder images after build (#6716)
* Clean up old add-on builder images after build

After a Docker engine update, the add-on builder image (docker:*-cli)
is pulled with a new version tag, leaving old versions behind. Clean
up old builder images after each successful add-on build using the
existing cleanup_old_images method.

The cleanup is done after build because cleanup_old_images needs the
current image to exist, and the builder image is only pulled on first
build (in run_command) after a Docker engine update.

Also change ADDON_BUILDER_IMAGE to use the short name "docker" instead
of the canonical "docker.io/library/docker", as Docker stores images
under the short name and the reference filter in cleanup_old_images
does not match the canonical form.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix tests for short builder image name

Update test assertions to use the short "docker" image name
instead of the canonical "docker.io/library/docker".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:00:03 +02:00
dependabot[bot]
8f3638ec0d Bump actions/github-script from 8.0.0 to 9.0.0 (#6722)
Bumps [actions/github-script](https://github.com/actions/github-script) from 8.0.0 to 9.0.0.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](ed597411d8...3a2844b7e9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: 9.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 09:18:20 +02:00
dependabot[bot]
e71b8670b5 Bump release-drafter/release-drafter from 7.1.1 to 7.2.0 (#6723)
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 7.1.1 to 7.2.0.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](139054aeaa...5de9358398)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 09:16:47 +02:00
dependabot[bot]
de8abe2815 Bump ruff from 0.15.9 to 0.15.10 (#6724)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.9 to 0.15.10.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.15.9...0.15.10)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.15.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-10 09:16:33 +02:00
Stefan Agner
a30f2509a3 Enable IPv6 on Supervisor network by default for all installations (#6720)
* Improve Docker network test coverage and infrastructure

Add test cases for enable_ipv6=None (no user setting) to
test_network_recreation, verifying existing behavior where None
leaves the network unchanged. Use pytest.param with descriptive IDs
for better test readability.

Add create_network_mock side_effect to the docker fixture so network
creation returns realistic metadata built from the provided params.
Remove redundant manual create mock setups from individual tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Enable IPv6 on Supervisor network by default for all installations

Previously, IPv6 was only enabled by default for new installations
(when enable_ipv6 config was None). Existing installations with
IPv4-only networks were left unchanged unless the user explicitly
set enable_ipv6 to true.

Now, when no explicit IPv6 setting exists, the network is migrated
to dual-stack on next boot. The same safety checks apply: migration
is blocked if user containers are running and requires a reboot.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026.04.0
2026-04-09 18:08:30 +02:00
Stefan Agner
321b692370 Consolidate Supervisor auto-update into updater reload task (#6705)
* Consolidate Supervisor auto-update into updater reload task

The separate _update_supervisor task (24h interval) was redundant since
_reload_updater (previously ~7.5h interval) already triggered the same
update when a new version was found. This meant Supervisor updates were
effectively checked every 7.5h, undermining the intent of #6633 and
#6638 to reduce update frequency and registry pressure.

Merge the two code paths into one: _reload_updater now directly calls
_auto_update_supervisor (with the same job conditions) when a new
version is detected. The reload interval is increased from ~7.5h to 24h
to match the originally intended update cadence.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add regression test for scheduled supervisor auto-update

Verify that the scheduled reload_updater task triggers exactly one
supervisor update when a new version is available. Uses event loop
time patching to simulate the 24h interval firing.

This guards against the previous bug where a separate _update_supervisor
task ran on its own schedule, causing duplicate update attempts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:45:58 +02:00
Stefan Agner
1fcfededac Let write-side OSError propagate during backup creation (#6704)
* Let OSError propagate during backup creation

Securetar's create_tar context manager uses a two-phase header write:
on enter it writes a placeholder tar header (size unknown), and on exit
_finalize_tar_entry seeks back to rewrite the header with the actual
size. If an OSError (e.g. ENOSPC) occurs mid-write, the inner tar entry
is left with truncated data and a placeholder header. Continuing to
write more entries on top of this produces a structurally invalid tar
file that cannot be restored.

Previously, _folder_save wrapped OSError as BackupError, which
store_folders then caught and swallowed — allowing the backup to
continue writing to an already corrupt outer tar. Similarly,
_create_finalize silently swallowed OSError when writing backup.json,
and the finally block in create() could raise a secondary OSError from
_close_outer_tarfile that replaced the original exception.

Securetar already distinguishes read vs write errors: read-side errors
(e.g. permission denied on a source file) are wrapped as AddFileError
(non-fatal, skip the file), while write-side OSError propagates as-is.

With this change, write-side OSError is wrapped as BackupFatalError
(a BackupError subclass) instead of plain BackupError. This ensures:
- store_folders/store_addons do not swallow it (they only catch
  BackupError, and re-raise BackupFatalError explicitly).
- The job decorator handles it as a HassioError (no extra Sentry
  event). Letting OSError bubble up raw would cause the job decorator
  to treat it as an unhandled exception, capturing it to Sentry and
  wrapping it as JobException — producing more Sentry noise, not less.
- _do_backup catches it via `except BackupError` and deletes the
  incomplete backup file. This is the correct behavior since the tar
  is structurally corrupt and not restorable.

Changes:
- Add BackupFatalError exception for write-side I/O errors.
- In create(), use except/else instead of finally so that finalization
  is skipped when an error already occurred during yield. This prevents
  a secondary exception from _close_outer_tarfile replacing the
  original error.
- In _create_finalize, raise BackupFatalError on OSError instead of
  swallowing it.
- In _folder_save, wrap OSError as BackupFatalError (not BackupError).
- In store_folders, re-raise BackupFatalError instead of swallowing.
- In store_supervisor_config, wrap OSError as BackupFatalError.

Fixes SUPERVISOR-B53
Fixes SUPERVISOR-1FAJ
Fixes SUPERVISOR-BJ4
Fixes SUPERVISOR-18KS
Fixes SUPERVISOR-1HE6

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Rename BackupFatalError to BackupFatalIOError

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:45:43 +02:00
Stefan Agner
4768bfc50d Wait for systemd-timesyncd to fully stop before setting time (#6715)
* Wait for systemd-timesyncd to stop before setting time

The previous 1-second sleep was not always enough for
systemd-timesyncd to fully stop, causing timedated to still reject
the set_time call with "Automatic time synchronization is enabled".
Instead, listen for the unit's ActiveState D-Bus property to become
inactive before proceeding, with a 10-second timeout.

Refs SUPERVISOR-92R

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add wait_for_active_state helper to SystemdUnit

Centralize the repeated pattern of listening for D-Bus
PropertiesChanged signals to wait for a systemd unit's ActiveState
to reach a target state. Refactor core.py, host/firewall.py, and
mounts/mount.py to use the new helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Test time sync with active-to-inactive state transition

Exercise the actual wait_for_active_state signal-driven transition
in the time sync test: start the mock unit as "active" and drive it
to "inactive" via a PropertiesChanged signal, rather than starting
it as "inactive" which would make the wait a no-op.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 14:44:41 +02:00
Stefan Agner
5cb8b303bc Revert "Disable hassio gateway protection rules in dev mode (#6658)" (#6714)
This reverts commit 0cb96c36b6.
2026-04-08 11:25:21 +02:00
dependabot[bot]
657f8027a5 Bump securetar from 2026.2.0 to 2026.4.1 (#6710)
* Bump securetar from 2026.2.0 to 2026.4.1

Bumps [securetar](https://github.com/pvizeli/securetar) from 2026.2.0 to 2026.4.1.
- [Release notes](https://github.com/pvizeli/securetar/releases)
- [Commits](https://github.com/pvizeli/securetar/compare/2026.2.0...2026.4.1)

---
updated-dependencies:
- dependency-name: securetar
  dependency-version: 2026.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Avoid using SecureTarFile path attribute

Avoid using SecureTarFile path attribute which can be None. Instead,
introduce tar_path which can't be None and move backup existence check
before creating the SecureTarFile instance.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2026-04-08 10:20:53 +02:00
dependabot[bot]
e295b8f1bc Bump pytest from 9.0.2 to 9.0.3 (#6713)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 9.0.2 to 9.0.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/9.0.2...9.0.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 9.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 09:48:56 +02:00
dependabot[bot]
4c071746b3 Bump types-pyyaml from 6.0.12.20250915 to 6.0.12.20260408 (#6712)
Bumps [types-pyyaml](https://github.com/python/typeshed) from 6.0.12.20250915 to 6.0.12.20260408.
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-pyyaml
  dependency-version: 6.0.12.20260408
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 09:48:43 +02:00
dependabot[bot]
5db908a965 Bump cryptography from 46.0.6 to 46.0.7 (#6711)
Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.6 to 46.0.7.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.6...46.0.7)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 09:48:30 +02:00
Mike Degatano
941f7cd2be Change addons to apps in all user-facing strings (#6696)
* Change addons to apps in all user-facing strings

* Fix grammar in errors

* Apply suggestions from code review

Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Stefan Agner <stefan@agner.ch>

---------

Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2026-04-07 18:54:40 +02:00
Stefan Agner
49960e0ddb Explicitly allow multiple exceptions listed without paratheses (#6706)
Explicitly allow Python 3.14 syntax for except clauses with multiple
exceptions without parentheses. Despite calling out Python 3.14, AI
commonly suggests to change this syntax.
2026-04-07 18:12:19 +02:00
Jan Čermák
1264dbedaa Make app builds work without build.yaml (#6694)
* Make app builds work without build.yaml

The builds are moving build configuration into the Dockerfile itself (base
image defaults via `ARG`, labels via `LABEL`). This change makes `build.yaml`
optional for local app builds while preserving backward compatibility for apps
that still define it.

Key changes:
* Track whether `build.yaml` was found, log a warning if it is.
* Skip `BUILD_FROM` build arg when no build file exists, letting the
  Dockerfile's own `ARG BUILD_FROM=...` default take effect.
* Always include all configured registry credentials in docker config instead
  of matching only the base image's registry.
* Only set `io.hass.name` and `io.hass.description` labels when non-empty, as
  they could be defined in the Dockerfile directly.
* Log a deprecation warning when `build.yaml` is present.

Refs home-assistant/epics#33

* Add-on -> app

* Remove FileConfiguration from AddonBuild base classes

Since we're deprecating usage of build.yaml, stop abusing the
FileConfiguration class for parsing the build file. The AddonBuild class
has been rewritten to be populated from the config file in an async
factory class method instead of in the overloaded load_file. While
cleaning up, the squash property has been removed as it's no longer used
anywhere and only the warning is printed if it's present in the parsed
config.
2026-04-07 17:32:25 +02:00
Stefan Agner
fec8e859fe Use sets for unhealthy and unsupported reasons (#6703)
* Use sets for unhealthy and unsupported reasons

The unhealthy and unsupported reason collections in ResolutionManager
are unique by nature and used manual deduplication with list operations.
Convert them to sets for a more natural data structure fit.

At serialization boundaries (REST API and WebSocket events), use
sorted() to ensure deterministic output order.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix set usage in Sentry filter and test

The unhealthy set in the Sentry filter context needs sorted() for
serialization, and the test was using list subscript on the set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:20:23 +02:00
Stefan Agner
07f02a23be Prevent Sentry event feedback loop from warning handler (#6700)
The custom warning_handler sends warnings to Sentry via
capture_exception. When the Sentry SDK's own HTTP transport triggers a
warning (e.g. urllib3 InsecureRequestWarning due to broken CA certs),
this creates a self-inducing feedback loop: the warning is captured,
sent to Sentry, which triggers another warning, and so on.

Skip capture_exception for warnings originating from Sentry SDK
background threads (identified by the "sentry-sdk." thread name
prefix). Warnings are still logged normally via _LOGGER.warning.

A dedicated test validates that the SDK's BackgroundWorker thread uses
the expected naming convention, so any future SDK change will be caught.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:20:06 +02:00
dependabot[bot]
2d279fcfd0 Bump ruff from 0.15.8 to 0.15.9 (#6701)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.8 to 0.15.9.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.15.8...0.15.9)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.15.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-03 10:17:15 +02:00
Stefan Agner
43ca846232 Adapt devcontainer.json for systemd-based devcontainer image (#6693)
Update devcontainer.json settings to work with the new systemd-based
devcontainer image (v4).

- Bump image tag to 4-supervisor to get the systemd-enabled image
- Set overrideCommand to false so the image's CMD (/sbin/init) runs
  as PID 1 instead of being replaced by VS Code's default sleep command
- Set remoteUser to vscode to preserve the non-root shell experience
  (required when overrideCommand is false, since VS Code no longer
  injects its own user-switching wrapper)
- Add /var/lib/containerd volume mount because modern Docker uses the
  containerd snapshotter, which stores layer data outside
  /var/lib/docker
- Add tmpfs on /tmp to match typical systemd expectations and avoid
  leftover state across container restarts
2026-04-02 14:40:54 +02:00
dependabot[bot]
ec1ad8e838 Bump dbus-fast from 4.0.0 to 4.0.4 (#6697)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 4.0.0 to 4.0.4.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v4.0.0...v4.0.4)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-version: 4.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 10:27:47 +02:00
Jan Čermák
a78f02eed8 Fix version/requirements parsing in setup.py, set version in Dockerfile (#6692)
* Fix version/requirements parsing in setup.py, set version in Dockerfile

Remove the step patching const.py with detected version in CI and do
this during Dockerfile version from BUILD_VERSION argument instead.

Also, fix parsing of the version in `setup.py` - it wasn't working
because it was splitting the files on "/n" instead of newlines,
resulting in all Python packages installed having version string set to
`9999.9.9.dev9999` instead of the expected version.

(Note: setuptools are doing a version string normalization, so the
installed package has stripped leading zeroes and the second component
is `9` instead of the literal `09` used in default string in all places.
Fixing this is out of scope of this change as the ideal solution would
be to change the versioning schema but it should be noted.)

Lastly, clean up builder.yaml environment variables (crane is not used
anymore after #6679).

* Generate setuptools-compatible version for PR builds

For PR builds, we're using plain commit SHA as the version. This is
perfectly fine for Docker tags but it's not acceptable for Python
package version. By fixing the setup.py bug this error surfaced. Work it
around by setting the Package version to the string we used previously
suffixed by the commit SHA as build metadata (delimited by `+`).
2026-04-01 16:01:46 +02:00
Jan Čermák
31636fe310 Add builder workflow to paths triggering rebuild on merge (#6691)
When only the workflow changes, CI doesn't trigger rebuild when the PR
is merged to the `main` branch. Since it's a legitimate build trigger,
add it to the paths list.
2026-04-01 10:26:51 +02:00
Jan Čermák
0b805a2c09 Fix builder multi-arch manifest step, use matrix prepare step (#6690)
The manifest step was failing because the image name wasn't set in the
env. Also we can standardize the workflow by using the shared matrix
prepare step.
2026-04-01 09:38:01 +02:00
dependabot[bot]
63a21de82d Bump mypy from 1.19.1 to 1.20.0 (#6689)
Bumps [mypy](https://github.com/python/mypy) from 1.19.1 to 1.20.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.19.1...v1.20.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-version: 1.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 08:59:33 +02:00
dependabot[bot]
5308d98bad Bump sentry-sdk from 2.56.0 to 2.57.0 (#6688)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.56.0 to 2.57.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.56.0...2.57.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.57.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 08:58:53 +02:00
dependabot[bot]
1372fc2b53 Bump orjson from 3.11.7 to 3.11.8 (#6687)
Bumps [orjson](https://github.com/ijl/orjson) from 3.11.7 to 3.11.8.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.11.7...3.11.8)

---
updated-dependencies:
- dependency-name: orjson
  dependency-version: 3.11.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 08:57:06 +02:00
dependabot[bot]
69eb1deb78 Bump aiohttp from 3.13.4 to 3.13.5 (#6686)
---
updated-dependencies:
- dependency-name: aiohttp
  dependency-version: 3.13.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 08:56:37 +02:00
dependabot[bot]
1b585a556b Bump getsentry/action-release from 3.5.0 to 3.6.0 (#6685)
Bumps [getsentry/action-release](https://github.com/getsentry/action-release) from 3.5.0 to 3.6.0.
- [Release notes](https://github.com/getsentry/action-release/releases)
- [Changelog](https://github.com/getsentry/action-release/blob/master/CHANGELOG.md)
- [Commits](dab6548b3c...5657c9e888)

---
updated-dependencies:
- dependency-name: getsentry/action-release
  dependency-version: 3.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 08:49:35 +02:00
Stefan Agner
667bd62742 Remove CLI command hint from unknown error messages (#6684)
* Remove CLI command hint from unknown error messages

Since #6303 introduced specific error messages for many cases,
the generic "check with 'ha supervisor logs'" hint in unknown
error messages is no longer as useful. Remove the CLI command
part while keeping the "Check supervisor logs for details" rider.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Use consistently "Supervisor logs" with capitalization

Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>
2026-03-31 18:09:14 +02:00
Jan Čermák
b1ea4ce52f Publish multi-arch manifest after finished build (#6683)
Publish multi-arch manifest (`hassio-supervisor` image) after the build
finishes. The step's `needs` are intentionally not matching `version`
step, as the build itself publishes the arch-prefixed image already, so
only build is needed for the manifest to be published as well.

Closes #6646
2026.03.3
2026-03-31 13:52:23 +02:00
Jan Čermák
ba9080dfdd Remove re-tagging of old Supervisor for unsupported architectures (#6679)
In #6347 we dropped the build for deprecated architectures and started
re-tagging of Supervisor 2025.11.5 images to make them available through
the tag of the latest version. This was to provide some interim period
of graceful handling of updates for devices which were not online at the
time when Supervisor dropped support for these architectures. As the
support was dropped almost 4 months ago already, the majority of users
should have hopefully migrated. The rest will now see Supervisor failing
to update with no message about architecture drop if they update from a
too old version. Since the re-tagged version also reported a failure to
update, the impact isn't so bad.
2026-03-31 11:30:12 +02:00
Stefan Agner
7f8a6f7e09 Drop unused crypto attribute from backups (#6682)
The "crypto" field in backup.json was introduced alongside encryption
support in 2018 to indicate the algorithm (aes128). Over time,
encryption moved into securetar and the field became write-only
metadata — no code reads it to make decisions. With securetar v3, the
field is now actively misleading since the actual encryption algorithm
differs from what "crypto": "aes128" suggests. Remove ATTR_CRYPTO and
CRYPTO_AES128 constants, stop writing "crypto" to new backups, and use
vol.Remove to silently strip the key when loading old backups that
still contain it.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 11:15:36 +02:00
Stefan Agner
a4a17a70a5 Add specific error message for registry authentication failures (#6678)
* Add specific error message for registry authentication failures

When a Docker image pull fails with 401 Unauthorized and registry
credentials are configured, raise DockerRegistryAuthError instead of
a generic DockerError. This surfaces a clear message to the user
("Docker registry authentication failed for <registry>. Check your
registry credentials") instead of "An unknown error occurred with
addon <name>".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add tests for registry authentication error handling

Test that a 401 during image pull raises DockerRegistryAuthError when
credentials are configured, and falls back to generic DockerError
when no credentials are present.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add tests for addon install/update/rebuild auth failure handling

Test that DockerRegistryAuthError propagates correctly through
addon install, update, and rebuild paths without being wrapped
in a generic AddonUnknownError.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:29:49 +02:00
Stefan Agner
e630ec1ac4 Include Docker registry configurations in backups (#6674)
* Include Docker registry configurations in backups

Docker registry credentials were removed from backup metadata in a prior
change to avoid exposing secrets in unencrypted data. Now that the encrypted
supervisor.tar inner archive exists, add docker.json alongside mounts.json
to securely backup and restore registry configurations.

On restore, registries from the backup are merged with any existing ones.
Old backups without docker.json are handled gracefully.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Increase test coverage by testing more error paths

* Address review feedback for Docker registry backup

Remove unnecessary dict() copy when serializing registries for backup
since the property already returns a dict.

Change DockerConfig.registries to use direct key access instead of
.get() with a default. The schema guarantees the key exists, and
.get() with a default would return a detached temporary dict that
silently discards updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:34:27 +02:00
Stefan Agner
be95349185 Reuse IMAGE_REGISTRY_REGEX for docker_image validation (#6667)
* Reuse IMAGE_REGISTRY_REGEX for docker_image validation

Replace the monolithic regex in docker_image validator with a
function-based approach that reuses get_registry_from_image() from
docker.utils for robust registry detection. This properly handles
domains, IPv4/IPv6 addresses, ports, and localhost while still
rejecting tags (managed separately by the add-on system).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address review feedback: reorder checks for efficiency

Check falsy value before isinstance, and empty path before tag check,
as suggested in PR review.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:33:11 +02:00
Stefan Agner
1fd78dfc4e Fix Docker Hub registry auth for containerd image store (#6677)
aiodocker derives ServerAddress for X-Registry-Auth by doing
image.partition("/"). For Docker Hub images like
"homeassistant/amd64-supervisor", this extracts "homeassistant"
(the namespace) instead of "docker.io" (the registry).

With the classic graphdriver image store, ServerAddress was never
checked and credentials were sent regardless. With the containerd
image store (default since Docker v29 / HAOS 15), the resolver
compares ServerAddress against the actual registry host and silently
drops credentials on mismatch, falling back to anonymous access.

Fix by prefixing Docker Hub images with "docker.io/" when registry
credentials are configured, so aiodocker sets ServerAddress correctly.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 14:43:18 +02:00
Stefan Agner
6b41fd4112 Improve codecov settings for more sensible defaults (#6676)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 13:24:22 +02:00
sepahewe
98bbb8869e Add support for negative numbers in apps options (#6673)
* Added support for negative numbers in options

* Do not allow -. as float

* Added tests for integers and floats in options.

* Fixed ruff errors

* Added tests for outside of int/float limits
2026-03-30 12:08:57 +02:00
dependabot[bot]
ef71ffb32b Bump aiohttp from 3.13.3 to 3.13.4 (#6675)
---
updated-dependencies:
- dependency-name: aiohttp
  dependency-version: 3.13.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 10:56:15 +02:00
Stefan Agner
713354bf56 Handle certain OSError in get_latest_mtime during directory walk (#6632)
Besides file not found also catch "Too many levels of symbolic links"
which can happen when there are symbolic link loops in the add-on/apps
repository.

Also improve error handling in the repository update process to catch
OSError when checking for local modifications and raise a specific
error that can be handled appropriately.

Fixes SUPERVISOR-1FJ0

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 09:13:48 +01:00
dependabot[bot]
e2db2315b3 Bump ruff from 0.15.7 to 0.15.8 (#6670)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.7 to 0.15.8.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.15.7...0.15.8)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.15.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 09:13:23 +01:00
dependabot[bot]
39afa70cf6 Bump codecov/codecov-action from 5.5.3 to 6.0.0 (#6669)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.5.3 to 6.0.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](1af58845a9...57e3a136b7)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-27 09:13:10 +01:00
Paul Tarjan
2b9c8282a4 Include network storage mount configurations in backups (#6411)
* Include network storage mount configurations in backups

When creating backups, now stores mount configurations (CIFS/NFS shares)
including server, share, credentials, and other settings. When restoring
from a backup, mount configurations are automatically restored.

This fixes the issue where network storage definitions for backups
were lost after restoring from a backup, requiring users to manually
reconfigure their network storage mounts.

Changes:
- Add ATTR_MOUNTS schema to backup validation
- Add store_mounts() method to save mount configs during backup
- Add restore_mounts() method to restore mount configs during restore
- Add MOUNTS stage to backup/restore job stages
- Update BackupManager to call mount backup/restore methods
- Add tests for mount backup/restore functionality

Fixes home-assistant/core#148663

* Address reviewer feedback for mount backup/restore

Changes based on PR review:
- Store mount configs in encrypted mounts.tar instead of unencrypted
  backup metadata (security fix for passwords)
- Separate mount restore into config save + async activation tasks
  (mounts activate in background, failures don't block restore)
- Add replace_default_backup_mount parameter to control whether to
  overwrite existing default mount setting
- Remove unnecessary broad exception handler for default mount setter
- Simplify schema: ATTR_MOUNTS is now just a boolean flag since
  actual data is in the encrypted tar file
- Update tests to reflect new async API and return types

* Fix code review issues in mount backup/restore

- Add bind mount handling for MEDIA and SHARE usage types in
  _activate_restored_mount() to mirror MountManager.create_mount()
- Fix double save_data() call by using needs_save flag
- Import MountUsage const for usage type checks

* Add pylint disable comments for protected member access

* Tighten broad exception handlers in mount backup restore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address second round of reviewer feedback

- Catch OSError separately and check errno.EBADMSG for drive health
- Validate mounts JSON against SCHEMA_MOUNTS_CONFIG before importing
- Use mount_data[ATTR_NAME] instead of .get("name", "unknown")
- Overwrite existing mounts on restore instead of skipping
- Move restore_mount/activate logic to MountManager (no more
  protected-access in Backup)
- Drop unused replace_default_backup_mount parameter
- Fix test_backup_progress: add mounts stage to expected events
- Fix test_store_mounts: avoid create_mount which requires dbus

* Rename mounts.tar to supervisor.tar for generic supervisor config

Rename the inner tar from mounts.tar to supervisor.tar so it can hold
multiple config files (mounts.json now, docker credentials later).
Rename store_mounts/restore_mounts to store_supervisor_config/
restore_supervisor_config and update stage names accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix pylint protected-access and test timeouts in backup tests

- Add pylint disable comment for _mounts protected access in test_backup.py
- Mock restore_supervisor_config in test_full_backup_to_mount and
  test_partial_backup_to_mount to avoid D-Bus mount activation during
  restore that causes timeouts in the test environment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address agners review feedback

- Change create_inner_tar() to create_tar() per #6575
- Remove "r" argument from SecureTarFile (now read-only by default)
- Change warning to info for missing mounts tar (old backups won't have it)
- Narrow exception handler to (MountError, vol.Invalid, KeyError, OSError)

* Update supervisor/backups/backup.py

* Address agners feedback: remove metadata flag, add mount feature check

- Remove ATTR_SUPERVISOR boolean flag from backup metadata; instead
  check for physical presence of supervisor.tar (like folder backups)
- Remove has_supervisor_config property
- Always attempt supervisor config restore (tar existence check handles it)
- Add HostFeature.MOUNT check in _activate_restored_mount before
  attempting to activate mounts on systems without mount support

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2026-03-26 17:08:16 -04:00
Stefan Agner
6525c8c231 Remove unused requests dependency (#6666)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:32:19 +01:00
Stefan Agner
612664e3d6 Fix build workflow by hardcoding architectures matrix (#6665)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 09:59:19 +01:00