Add go2rtc recommended version (#130508)

This commit is contained in:
Robert Resch 2024-11-13 11:01:05 +01:00 committed by GitHub
parent 0ac00ef092
commit 2eaaadd736
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 94 additions and 11 deletions

View file

@ -90,7 +90,7 @@ repos:
pass_filenames: false pass_filenames: false
language: script language: script
types: [text] types: [text]
files: ^(script/hassfest/metadata\.py|homeassistant/const\.py$|pyproject\.toml)$ files: ^(script/hassfest/metadata\.py|homeassistant/const\.py$|pyproject\.toml|homeassistant/components/go2rtc/const\.py)$
- id: hassfest-mypy-config - id: hassfest-mypy-config
name: hassfest-mypy-config name: hassfest-mypy-config
entry: script/run-in-env.sh python3 -m script.hassfest -p mypy_config entry: script/run-in-env.sh python3 -m script.hassfest -p mypy_config

View file

@ -4,6 +4,7 @@ import logging
import shutil import shutil
from aiohttp.client_exceptions import ClientConnectionError, ServerConnectionError from aiohttp.client_exceptions import ClientConnectionError, ServerConnectionError
from awesomeversion import AwesomeVersion
from go2rtc_client import Go2RtcRestClient from go2rtc_client import Go2RtcRestClient
from go2rtc_client.exceptions import Go2RtcClientError, Go2RtcVersionError from go2rtc_client.exceptions import Go2RtcClientError, Go2RtcVersionError
from go2rtc_client.ws import ( from go2rtc_client.ws import (
@ -32,13 +33,23 @@ from homeassistant.config_entries import SOURCE_SYSTEM, ConfigEntry
from homeassistant.const import CONF_URL, EVENT_HOMEASSISTANT_STOP from homeassistant.const import CONF_URL, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import Event, HomeAssistant, callback from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, discovery_flow from homeassistant.helpers import (
config_validation as cv,
discovery_flow,
issue_registry as ir,
)
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util.hass_dict import HassKey from homeassistant.util.hass_dict import HassKey
from homeassistant.util.package import is_docker_env from homeassistant.util.package import is_docker_env
from .const import CONF_DEBUG_UI, DEBUG_UI_URL_MESSAGE, DOMAIN, HA_MANAGED_URL from .const import (
CONF_DEBUG_UI,
DEBUG_UI_URL_MESSAGE,
DOMAIN,
HA_MANAGED_URL,
RECOMMENDED_VERSION,
)
from .server import Server from .server import Server
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -147,7 +158,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# Validate the server URL # Validate the server URL
try: try:
client = Go2RtcRestClient(async_get_clientsession(hass), url) client = Go2RtcRestClient(async_get_clientsession(hass), url)
await client.validate_server_version() version = await client.validate_server_version()
if version < AwesomeVersion(RECOMMENDED_VERSION):
ir.async_create_issue(
hass,
DOMAIN,
"recommended_version",
is_fixable=False,
is_persistent=False,
severity=ir.IssueSeverity.WARNING,
translation_key="recommended_version",
translation_placeholders={
"recommended_version": RECOMMENDED_VERSION,
"current_version": str(version),
},
)
except Go2RtcClientError as err: except Go2RtcClientError as err:
if isinstance(err.__cause__, _RETRYABLE_ERRORS): if isinstance(err.__cause__, _RETRYABLE_ERRORS):
raise ConfigEntryNotReady( raise ConfigEntryNotReady(

View file

@ -6,3 +6,4 @@ CONF_DEBUG_UI = "debug_ui"
DEBUG_UI_URL_MESSAGE = "Url and debug_ui cannot be set at the same time." DEBUG_UI_URL_MESSAGE = "Url and debug_ui cannot be set at the same time."
HA_MANAGED_API_PORT = 11984 HA_MANAGED_API_PORT = 11984
HA_MANAGED_URL = f"http://localhost:{HA_MANAGED_API_PORT}/" HA_MANAGED_URL = f"http://localhost:{HA_MANAGED_API_PORT}/"
RECOMMENDED_VERSION = "1.9.7"

View file

@ -0,0 +1,8 @@
{
"issues": {
"recommended_version": {
"title": "Outdated go2rtc server detected",
"description": "We detected that you are using an outdated go2rtc server version. For the best experience, we recommend updating the go2rtc server to version `{recommended_version}`.\nCurrently you are using version `{current_version}`."
}
}
}

View file

@ -4,6 +4,7 @@ from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from homeassistant import core from homeassistant import core
from homeassistant.components.go2rtc.const import RECOMMENDED_VERSION as GO2RTC_VERSION
from homeassistant.const import Platform from homeassistant.const import Platform
from homeassistant.util import executor, thread from homeassistant.util import executor, thread
from script.gen_requirements_all import gather_recursive_requirements from script.gen_requirements_all import gather_recursive_requirements
@ -112,8 +113,6 @@ LABEL "com.github.actions.icon"="terminal"
LABEL "com.github.actions.color"="gray-dark" LABEL "com.github.actions.color"="gray-dark"
""" """
_GO2RTC_VERSION = "1.9.7"
def _get_package_versions(file: Path, packages: set[str]) -> dict[str, str]: def _get_package_versions(file: Path, packages: set[str]) -> dict[str, str]:
package_versions: dict[str, str] = {} package_versions: dict[str, str] = {}
@ -197,7 +196,7 @@ def _generate_files(config: Config) -> list[File]:
DOCKERFILE_TEMPLATE.format( DOCKERFILE_TEMPLATE.format(
timeout=timeout, timeout=timeout,
**package_versions, **package_versions,
go2rtc=_GO2RTC_VERSION, go2rtc=GO2RTC_VERSION,
), ),
config.root / "Dockerfile", config.root / "Dockerfile",
), ),

View file

@ -3,9 +3,11 @@
from collections.abc import Generator from collections.abc import Generator
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
from awesomeversion import AwesomeVersion
from go2rtc_client.rest import _StreamClient, _WebRTCClient from go2rtc_client.rest import _StreamClient, _WebRTCClient
import pytest import pytest
from homeassistant.components.go2rtc.const import RECOMMENDED_VERSION
from homeassistant.components.go2rtc.server import Server from homeassistant.components.go2rtc.server import Server
GO2RTC_PATH = "homeassistant.components.go2rtc" GO2RTC_PATH = "homeassistant.components.go2rtc"
@ -23,7 +25,9 @@ def rest_client() -> Generator[AsyncMock]:
client = mock_client.return_value client = mock_client.return_value
client.streams = streams = Mock(spec_set=_StreamClient) client.streams = streams = Mock(spec_set=_StreamClient)
streams.list.return_value = {} streams.list.return_value = {}
client.validate_server_version = AsyncMock() client.validate_server_version = AsyncMock(
return_value=AwesomeVersion(RECOMMENDED_VERSION)
)
client.webrtc = Mock(spec_set=_WebRTCClient) client.webrtc = Mock(spec_set=_WebRTCClient)
yield client yield client

View file

@ -6,6 +6,7 @@ from typing import NamedTuple
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
from aiohttp.client_exceptions import ClientConnectionError, ServerConnectionError from aiohttp.client_exceptions import ClientConnectionError, ServerConnectionError
from awesomeversion import AwesomeVersion
from go2rtc_client import Stream from go2rtc_client import Stream
from go2rtc_client.exceptions import Go2RtcClientError, Go2RtcVersionError from go2rtc_client.exceptions import Go2RtcClientError, Go2RtcVersionError
from go2rtc_client.models import Producer from go2rtc_client.models import Producer
@ -36,10 +37,12 @@ from homeassistant.components.go2rtc.const import (
CONF_DEBUG_UI, CONF_DEBUG_UI,
DEBUG_UI_URL_MESSAGE, DEBUG_UI_URL_MESSAGE,
DOMAIN, DOMAIN,
RECOMMENDED_VERSION,
) )
from homeassistant.config_entries import ConfigEntry, ConfigEntryState, ConfigFlow from homeassistant.config_entries import ConfigEntry, ConfigEntryState, ConfigFlow
from homeassistant.const import CONF_URL from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -199,6 +202,7 @@ async def init_test_integration(
async def _test_setup_and_signaling( async def _test_setup_and_signaling(
hass: HomeAssistant, hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
rest_client: AsyncMock, rest_client: AsyncMock,
ws_client: Mock, ws_client: Mock,
config: ConfigType, config: ConfigType,
@ -211,6 +215,7 @@ async def _test_setup_and_signaling(
assert await async_setup_component(hass, DOMAIN, config) assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done(wait_background_tasks=True) await hass.async_block_till_done(wait_background_tasks=True)
assert issue_registry.async_get_issue(DOMAIN, "recommended_version") is None
config_entries = hass.config_entries.async_entries(DOMAIN) config_entries = hass.config_entries.async_entries(DOMAIN)
assert len(config_entries) == 1 assert len(config_entries) == 1
assert config_entries[0].state == ConfigEntryState.LOADED assert config_entries[0].state == ConfigEntryState.LOADED
@ -306,6 +311,7 @@ async def _test_setup_and_signaling(
@pytest.mark.parametrize("has_go2rtc_entry", [True, False]) @pytest.mark.parametrize("has_go2rtc_entry", [True, False])
async def test_setup_go_binary( async def test_setup_go_binary(
hass: HomeAssistant, hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
rest_client: AsyncMock, rest_client: AsyncMock,
ws_client: Mock, ws_client: Mock,
server: AsyncMock, server: AsyncMock,
@ -324,7 +330,13 @@ async def test_setup_go_binary(
server_start.assert_called_once() server_start.assert_called_once()
await _test_setup_and_signaling( await _test_setup_and_signaling(
hass, rest_client, ws_client, config, after_setup, init_test_integration hass,
issue_registry,
rest_client,
ws_client,
config,
after_setup,
init_test_integration,
) )
await hass.async_stop() await hass.async_stop()
@ -340,8 +352,9 @@ async def test_setup_go_binary(
], ],
) )
@pytest.mark.parametrize("has_go2rtc_entry", [True, False]) @pytest.mark.parametrize("has_go2rtc_entry", [True, False])
async def test_setup_go( async def test_setup(
hass: HomeAssistant, hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
rest_client: AsyncMock, rest_client: AsyncMock,
ws_client: Mock, ws_client: Mock,
server: Mock, server: Mock,
@ -359,7 +372,13 @@ async def test_setup_go(
server.assert_not_called() server.assert_not_called()
await _test_setup_and_signaling( await _test_setup_and_signaling(
hass, rest_client, ws_client, config, after_setup, init_test_integration hass,
issue_registry,
rest_client,
ws_client,
config,
after_setup,
init_test_integration,
) )
mock_get_binary.assert_not_called() mock_get_binary.assert_not_called()
@ -711,3 +730,30 @@ async def test_config_entry_remove(hass: HomeAssistant) -> None:
assert len(hass.config_entries.async_entries(DOMAIN)) == 1 assert len(hass.config_entries.async_entries(DOMAIN)) == 1
assert not await hass.config_entries.async_setup(config_entry.entry_id) assert not await hass.config_entries.async_setup(config_entry.entry_id)
assert len(hass.config_entries.async_entries(DOMAIN)) == 0 assert len(hass.config_entries.async_entries(DOMAIN)) == 0
@pytest.mark.parametrize("config", [{DOMAIN: {CONF_URL: "http://localhost:1984"}}])
@pytest.mark.usefixtures("server")
async def test_setup_with_recommended_version_repair(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
rest_client: AsyncMock,
config: ConfigType,
) -> None:
"""Test setup integration entry fails."""
rest_client.validate_server_version.return_value = AwesomeVersion("1.9.5")
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done(wait_background_tasks=True)
# Verify the issue is created
issue = issue_registry.async_get_issue(DOMAIN, "recommended_version")
assert issue
assert issue.is_fixable is False
assert issue.is_persistent is False
assert issue.severity == ir.IssueSeverity.WARNING
assert issue.issue_id == "recommended_version"
assert issue.translation_key == "recommended_version"
assert issue.translation_placeholders == {
"recommended_version": RECOMMENDED_VERSION,
"current_version": "1.9.5",
}