mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Add update entity to immich integration (#147273)
* add update entity * remove unneccessary entity description * rename update entity to version * simplify test * define static attribute outside of the constructor * move min version check into coordinator
This commit is contained in:
parent
d4e7667ea0
commit
41e53297c2
@ -20,7 +20,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
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:
|
||||
|
@ -13,7 +13,9 @@ from aioimmich.server.models import (
|
||||
ImmichServerAbout,
|
||||
ImmichServerStatistics,
|
||||
ImmichServerStorage,
|
||||
ImmichServerVersionCheck,
|
||||
)
|
||||
from awesomeversion import AwesomeVersion
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SSL
|
||||
@ -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]
|
||||
@ -71,9 +74,16 @@ class ImmichDataUpdateCoordinator(DataUpdateCoordinator[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
|
||||
)
|
||||
|
@ -68,6 +68,11 @@
|
||||
"usage_by_videos": {
|
||||
"name": "Disk used by videos"
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"update": {
|
||||
"name": "Version"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
57
homeassistant/components/immich/update.py
Normal file
57
homeassistant/components/immich/update.py
Normal file
@ -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}"
|
||||
)
|
@ -8,6 +8,7 @@ from aioimmich.server.models import (
|
||||
ImmichServerAbout,
|
||||
ImmichServerStatistics,
|
||||
ImmichServerStorage,
|
||||
ImmichServerVersionCheck,
|
||||
)
|
||||
from aioimmich.users.models import ImmichUserObject
|
||||
import pytest
|
||||
@ -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",
|
||||
}
|
||||
@ -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
|
||||
|
||||
|
||||
|
@ -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',
|
||||
@ -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({
|
||||
|
61
tests/components/immich/snapshots/test_update.ambr
Normal file
61
tests/components/immich/snapshots/test_update.ambr
Normal file
@ -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
tests/components/immich/test_update.py
Normal file
45
tests/components/immich/test_update.py
Normal file
@ -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…
x
Reference in New Issue
Block a user