Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/esphome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"mqtt": ["esphome/discover/#"],
"quality_scale": "platinum",
"requirements": [
"aioesphomeapi==32.2.4",
"aioesphomeapi==33.0.0",
"esphome-dashboard-api==1.3.0",
"bleak-esphome==2.16.0"
],
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/immich/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from .coordinator import ImmichConfigEntry, ImmichDataUpdateCoordinator

PLATFORMS: list[Platform] = [Platform.SENSOR]
PLATFORMS: list[Platform] = [Platform.SENSOR, Platform.UPDATE]


async def async_setup_entry(hass: HomeAssistant, entry: ImmichConfigEntry) -> bool:
Expand All @@ -33,6 +33,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ImmichConfigEntry) -> bo
entry.data[CONF_HOST],
entry.data[CONF_PORT],
entry.data[CONF_SSL],
"home-assistant",
)

try:
Expand Down
12 changes: 11 additions & 1 deletion homeassistant/components/immich/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
ImmichServerAbout,
ImmichServerStatistics,
ImmichServerStorage,
ImmichServerVersionCheck,
)
from awesomeversion import AwesomeVersion

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SSL
Expand All @@ -33,6 +35,7 @@ class ImmichData:
server_about: ImmichServerAbout
server_storage: ImmichServerStorage
server_usage: ImmichServerStatistics | None
server_version_check: ImmichServerVersionCheck | None


type ImmichConfigEntry = ConfigEntry[ImmichDataUpdateCoordinator]
Expand Down Expand Up @@ -71,9 +74,16 @@ async def _async_update_data(self) -> ImmichData:
if self.is_admin
else None
)
server_version_check = (
await self.api.server.async_get_version_check()
if AwesomeVersion(server_about.version) >= AwesomeVersion("v1.134.0")
else None
)
except ImmichUnauthorizedError as err:
raise ConfigEntryAuthFailed from err
except CONNECT_ERRORS as err:
raise UpdateFailed from err

return ImmichData(server_about, server_storage, server_usage)
return ImmichData(
server_about, server_storage, server_usage, server_version_check
)
2 changes: 1 addition & 1 deletion homeassistant/components/immich/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "local_polling",
"loggers": ["aioimmich"],
"quality_scale": "silver",
"requirements": ["aioimmich==0.9.1"]
"requirements": ["aioimmich==0.10.1"]
}
5 changes: 5 additions & 0 deletions homeassistant/components/immich/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
"usage_by_videos": {
"name": "Disk used by videos"
}
},
"update": {
"update": {
"name": "Version"
}
}
}
}
57 changes: 57 additions & 0 deletions homeassistant/components/immich/update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Update platform for the Immich integration."""

from __future__ import annotations

from homeassistant.components.update import UpdateEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import ImmichConfigEntry, ImmichDataUpdateCoordinator
from .entity import ImmichEntity

# Coordinator is used to centralize the data updates
PARALLEL_UPDATES = 0


async def async_setup_entry(
hass: HomeAssistant,
entry: ImmichConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add immich server update entity."""
coordinator = entry.runtime_data

if coordinator.data.server_version_check is not None:
async_add_entities([ImmichUpdateEntity(coordinator)])


class ImmichUpdateEntity(ImmichEntity, UpdateEntity):
"""Define Immich update entity."""

_attr_translation_key = "update"

def __init__(
self,
coordinator: ImmichDataUpdateCoordinator,
) -> None:
"""Initialize."""
super().__init__(coordinator)
self._attr_unique_id = f"{coordinator.config_entry.unique_id}_update"

@property
def installed_version(self) -> str:
"""Current installed immich server version."""
return self.coordinator.data.server_about.version

@property
def latest_version(self) -> str:
"""Available new immich server version."""
assert self.coordinator.data.server_version_check
return self.coordinator.data.server_version_check.release_version

@property
def release_url(self) -> str | None:
"""URL to the full release notes of the new immich server version."""
return (
f"https://github.com/immich-app/immich/releases/tag/{self.latest_version}"
)
1 change: 1 addition & 0 deletions homeassistant/components/switchbot_cloud/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ async def async_setup_entry(
for description in BINARY_SENSOR_DESCRIPTIONS_BY_DEVICE_TYPES[
device.device_type
]
if device.device_type in BINARY_SENSOR_DESCRIPTIONS_BY_DEVICE_TYPES
)


Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/switchbot_cloud/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ async def async_setup_entry(
SwitchBotCloudSensor(data.api, device, coordinator, description)
for device, coordinator in data.devices.sensors
for description in SENSOR_DESCRIPTIONS_BY_DEVICE_TYPES[device.device_type]
if device.device_type in SENSOR_DESCRIPTIONS_BY_DEVICE_TYPES
)


Expand Down
4 changes: 2 additions & 2 deletions requirements_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions requirements_test_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 16 additions & 9 deletions tests/components/immich/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ImmichServerAbout,
ImmichServerStatistics,
ImmichServerStorage,
ImmichServerVersionCheck,
)
from aioimmich.users.models import ImmichUserObject
import pytest
Expand Down Expand Up @@ -79,21 +80,21 @@ def mock_immich_server() -> AsyncMock:
mock = AsyncMock(spec=ImmichServer)
mock.async_get_about_info.return_value = ImmichServerAbout.from_dict(
{
"version": "v1.132.3",
"versionUrl": "https://github.com/immich-app/immich/releases/tag/v1.132.3",
"version": "v1.134.0",
"versionUrl": "https://github.com/immich-app/immich/releases/tag/v1.134.0",
"licensed": False,
"build": "14709928600",
"buildUrl": "https://github.com/immich-app/immich/actions/runs/14709928600",
"buildImage": "v1.132.3",
"build": "15281783550",
"buildUrl": "https://github.com/immich-app/immich/actions/runs/15281783550",
"buildImage": "v1.134.0",
"buildImageUrl": "https://github.com/immich-app/immich/pkgs/container/immich-server",
"repository": "immich-app/immich",
"repositoryUrl": "https://github.com/immich-app/immich",
"sourceRef": "v1.132.3",
"sourceCommit": "02994883fe3f3972323bb6759d0170a4062f5236",
"sourceUrl": "https://github.com/immich-app/immich/commit/02994883fe3f3972323bb6759d0170a4062f5236",
"sourceRef": "v1.134.0",
"sourceCommit": "58ae77ec9204a2e43a8cb2f1fd27482af40d0891",
"sourceUrl": "https://github.com/immich-app/immich/commit/58ae77ec9204a2e43a8cb2f1fd27482af40d0891",
"nodejs": "v22.14.0",
"exiftool": "13.00",
"ffmpeg": "7.0.2-7",
"ffmpeg": "7.0.2-9",
"libvips": "8.16.1",
"imagemagick": "7.1.1-47",
}
Expand Down Expand Up @@ -130,6 +131,12 @@ def mock_immich_server() -> AsyncMock:
],
}
)
mock.async_get_version_check.return_value = ImmichServerVersionCheck.from_dict(
{
"checkedAt": "2025-06-21T16:35:10.352Z",
"releaseVersion": "v1.135.3",
}
)
return mock


Expand Down
22 changes: 13 additions & 9 deletions tests/components/immich/snapshots/test_diagnostics.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
dict({
'data': dict({
'server_about': dict({
'build': '14709928600',
'build_image': 'v1.132.3',
'build': '15281783550',
'build_image': 'v1.134.0',
'build_image_url': 'https://github.com/immich-app/immich/pkgs/container/immich-server',
'build_url': 'https://github.com/immich-app/immich/actions/runs/14709928600',
'build_url': 'https://github.com/immich-app/immich/actions/runs/15281783550',
'exiftool': '13.00',
'ffmpeg': '7.0.2-7',
'ffmpeg': '7.0.2-9',
'imagemagick': '7.1.1-47',
'libvips': '8.16.1',
'licensed': False,
'nodejs': 'v22.14.0',
'repository': 'immich-app/immich',
'repository_url': 'https://github.com/immich-app/immich',
'source_commit': '02994883fe3f3972323bb6759d0170a4062f5236',
'source_ref': 'v1.132.3',
'source_url': 'https://github.com/immich-app/immich/commit/02994883fe3f3972323bb6759d0170a4062f5236',
'version': 'v1.132.3',
'version_url': 'https://github.com/immich-app/immich/releases/tag/v1.132.3',
'source_commit': '58ae77ec9204a2e43a8cb2f1fd27482af40d0891',
'source_ref': 'v1.134.0',
'source_url': 'https://github.com/immich-app/immich/commit/58ae77ec9204a2e43a8cb2f1fd27482af40d0891',
'version': 'v1.134.0',
'version_url': 'https://github.com/immich-app/immich/releases/tag/v1.134.0',
}),
'server_storage': dict({
'disk_available': '136.3 GiB',
Expand Down Expand Up @@ -49,6 +49,10 @@
'usage_videos': 65234281361,
'videos': 1836,
}),
'server_version_check': dict({
'checked_at': '2025-06-21T16:35:10.352000+00:00',
'release_version': 'v1.135.3',
}),
}),
'entry': dict({
'data': dict({
Expand Down
61 changes: 61 additions & 0 deletions tests/components/immich/snapshots/test_update.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# serializer version: 1
# name: test_update[update.someone_version-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'update',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'update.someone_version',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Version',
'platform': 'immich',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'update',
'unique_id': 'e7ef5713-9dab-4bd4-b899-715b0ca4379e_update',
'unit_of_measurement': None,
})
# ---
# name: test_update[update.someone_version-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'auto_update': False,
'display_precision': 0,
'entity_picture': 'https://brands.home-assistant.io/_/immich/icon.png',
'friendly_name': 'Someone Version',
'in_progress': False,
'installed_version': 'v1.134.0',
'latest_version': 'v1.135.3',
'release_summary': None,
'release_url': 'https://github.com/immich-app/immich/releases/tag/v1.135.3',
'skipped_version': None,
'supported_features': <UpdateEntityFeature: 0>,
'title': None,
'update_percentage': None,
}),
'context': <ANY>,
'entity_id': 'update.someone_version',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
45 changes: 45 additions & 0 deletions tests/components/immich/test_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Test the Immich update platform."""

from unittest.mock import Mock, patch

from syrupy.assertion import SnapshotAssertion

from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er

from . import setup_integration

from tests.common import MockConfigEntry, snapshot_platform


async def test_update(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_immich: Mock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Immich update platform."""

with patch("homeassistant.components.immich.PLATFORMS", [Platform.UPDATE]):
await setup_integration(hass, mock_config_entry)

await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)


async def test_update_min_version(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_immich: Mock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Immich update platform with min version not installed."""

mock_immich.server.async_get_about_info.return_value.version = "v1.132.3"

with patch("homeassistant.components.immich.PLATFORMS", [Platform.UPDATE]):
await setup_integration(hass, mock_config_entry)

assert not hass.states.async_all()
Loading
Loading