Update HACS

This commit is contained in:
root
2022-10-30 09:47:33 -07:00
parent 791369c66a
commit 108f9c24cc
18 changed files with 146 additions and 49 deletions

View File

@@ -29,7 +29,6 @@ from .enums import ConfigurationType, HacsDisabledReason, HacsStage, LovelaceMod
from .frontend import async_register_frontend
from .utils.configuration_schema import hacs_config_combined
from .utils.data import HacsData
from .utils.platform_setup import async_setup_entity_platforms
from .utils.queue_manager import QueueManager
from .utils.version import version_left_higher_or_equal_then_right
from .websocket import async_register_websocket_commands
@@ -169,9 +168,7 @@ async def async_initialize_integration(
hacs.log.info("Update entities are only supported when using UI configuration")
else:
await async_setup_entity_platforms(
hacs,
hass,
hass.config_entries.async_setup_platforms(
config_entry,
[Platform.SENSOR, Platform.UPDATE]
if hacs.configuration.experimental

View File

@@ -28,10 +28,11 @@ from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.const import EVENT_HOMEASSISTANT_FINAL_WRITE, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.issue_registry import async_create_issue, IssueSeverity
from homeassistant.loader import Integration
from homeassistant.util import dt
from .const import TV
from .const import DOMAIN, TV
from .enums import (
ConfigurationType,
HacsCategory,
@@ -54,7 +55,6 @@ from .repositories import RERPOSITORY_CLASSES
from .utils.decode import decode_content
from .utils.json import json_loads
from .utils.logger import LOGGER
from .utils.platform_setup import async_setup_entity_platforms
from .utils.queue_manager import QueueManager
from .utils.store import async_load_from_store, async_save_to_store
@@ -187,8 +187,8 @@ class HacsRepositories:
_default_repositories: set[str] = field(default_factory=set)
_repositories: list[HacsRepository] = field(default_factory=list)
_repositories_by_full_name: dict[str, str] = field(default_factory=dict)
_repositories_by_id: dict[str, str] = field(default_factory=dict)
_repositories_by_full_name: dict[str, HacsRepository] = field(default_factory=dict)
_repositories_by_id: dict[str, HacsRepository] = field(default_factory=dict)
_removed_repositories: list[RemovedRepository] = field(default_factory=list)
@property
@@ -213,9 +213,16 @@ class HacsRepositories:
if repo_id == "0":
return
if self.is_registered(repository_id=repo_id):
if registered_repo := self._repositories_by_id.get(repo_id):
if registered_repo.data.full_name == repository.data.full_name:
return
self.unregister(registered_repo)
registered_repo.data.full_name = repository.data.full_name
registered_repo.data.new = False
repository = registered_repo
if repository not in self._repositories:
self._repositories.append(repository)
@@ -563,11 +570,6 @@ class HacsBase:
if repository_id is not None:
repository.data.id = repository_id
if str(repository.data.id) != "0" and (
exists := self.repositories.get_by_id(repository.data.id)
):
self.repositories.unregister(exists)
else:
if self.hass is not None and ((check and repository.data.new) or self.status.new):
self.async_dispatch(
@@ -730,10 +732,7 @@ class HacsBase:
entry=self.configuration.config_entry,
platforms=platforms,
)
await async_setup_entity_platforms(
self, self.hass, self.configuration.config_entry, platforms
)
self.hass.config_entries.async_setup_platforms(self.configuration.config_entry, platforms)
@callback
def async_dispatch(self, signal: HacsDispatchEvent, data: dict | None = None) -> None:
@@ -881,7 +880,23 @@ class HacsBase:
continue
if repository.data.full_name in self.common.ignored_repositories:
continue
if repository.data.installed and removed.removal_type != "critical":
if repository.data.installed:
if removed.removal_type != "critical":
if self.configuration.experimental:
async_create_issue(
hass=self.hass,
domain=DOMAIN,
issue_id=f"removed_{repository.data.id}",
is_fixable=False,
issue_domain=DOMAIN,
severity=IssueSeverity.WARNING,
translation_key="removed",
translation_placeholders={
"name": repository.data.full_name,
"reason": removed.reason,
"repositry_id": repository.data.id,
},
)
self.log.warning(
"You have '%s' installed with HACS "
"this repository has been removed from HACS, please consider removing it. "

View File

@@ -6,7 +6,7 @@ from aiogithubapi.common.const import ACCEPT_HEADERS
NAME_SHORT = "HACS"
DOMAIN = "hacs"
CLIENT_ID = "395a8e669c5de9f7c6e8"
MINIMUM_HA_VERSION = "2022.4.0"
MINIMUM_HA_VERSION = "2022.10.0"
TV = TypeVar("TV")

View File

@@ -8,8 +8,11 @@ from homeassistant.components.http import HomeAssistantView
from homeassistant.core import HomeAssistant, callback
from .const import DOMAIN
from .hacs_frontend import locate_dir
from .hacs_frontend.version import VERSION as FE_VERSION
from .hacs_frontend import locate_dir, VERSION as FE_VERSION
from .hacs_frontend_experimental import (
locate_dir as experimental_locate_dir,
VERSION as EXPERIMENTAL_FE_VERSION,
)
URL_BASE = "/hacsfiles"
@@ -30,6 +33,11 @@ def async_register_frontend(hass: HomeAssistant, hacs: HacsBase) -> None:
"<HacsFrontend> Frontend development mode enabled. Do not run in production!"
)
hass.http.register_view(HacsFrontendDev())
elif hacs.configuration.experimental:
hacs.log.info("<HacsFrontend> Using experimental frontend")
hass.http.register_static_path(
f"{URL_BASE}/frontend", experimental_locate_dir(), cache_headers=False
)
else:
#
hass.http.register_static_path(f"{URL_BASE}/frontend", locate_dir(), cache_headers=False)
@@ -56,7 +64,9 @@ def async_register_frontend(hass: HomeAssistant, hacs: HacsBase) -> None:
cache_headers=use_cache,
)
hacs.frontend_version = FE_VERSION
hacs.frontend_version = (
FE_VERSION if not hacs.configuration.experimental else EXPERIMENTAL_FE_VERSION
)
# Add to sidepanel if needed
if DOMAIN not in hass.data.get("frontend_panels", {}):
@@ -70,7 +80,7 @@ def async_register_frontend(hass: HomeAssistant, hacs: HacsBase) -> None:
"name": "hacs-frontend",
"embed_iframe": True,
"trust_external": False,
"js_url": f"/hacsfiles/frontend/entrypoint.js?hacstag={FE_VERSION}",
"js_url": f"/hacsfiles/frontend/entrypoint.js?hacstag={hacs.frontend_version}",
}
},
require_admin=True,

View File

@@ -1,9 +1,9 @@
try {
new Function("import('/hacsfiles/frontend/main-7bc9a818.js')")();
new Function("import('/hacsfiles/frontend/main-ad130be7.js')")();
} catch (err) {
var el = document.createElement('script');
el.src = '/hacsfiles/frontend/main-7bc9a818.js';
el.src = '/hacsfiles/frontend/main-ad130be7.js';
el.type = 'module';
document.body.appendChild(el);
}

View File

@@ -1,3 +1,3 @@
{
"./src/main.ts": "main-7bc9a818.js"
"./src/main.ts": "main-ad130be7.js"
}

View File

@@ -1 +1 @@
VERSION="20220714083628"
VERSION="20220906112053"

View File

@@ -8,7 +8,8 @@
"websocket_api",
"frontend",
"persistent_notification",
"lovelace"
"lovelace",
"repairs"
],
"documentation": "https://hacs.xyz/docs/configuration/start",
"domain": "hacs",
@@ -18,5 +19,5 @@
"requirements": [
"aiogithubapi>=22.2.4"
],
"version": "1.26.2"
"version": "1.28.3"
}

View File

@@ -18,7 +18,7 @@ from aiogithubapi import (
from aiogithubapi.const import BASE_API_URL
from aiogithubapi.objects.repository import AIOGitHubAPIRepository
import attr
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers import device_registry as dr, issue_registry as ir
from ..const import DOMAIN
from ..enums import ConfigurationType, HacsDispatchEvent, RepositoryFile
@@ -734,6 +734,7 @@ class HacsRepository:
)
await self.async_remove_entity_device()
ir.async_delete_issue(self.hacs.hass, DOMAIN, f"removed_{self.data.id}")
async def remove_local_directory(self) -> None:
"""Check the local directory."""
@@ -993,7 +994,12 @@ class HacsRepository:
releases.append(release)
return releases
async def common_update_data(self, ignore_issues: bool = False, force: bool = False) -> None:
async def common_update_data(
self,
ignore_issues: bool = False,
force: bool = False,
retry=False,
) -> None:
"""Common update data."""
releases = []
try:
@@ -1072,6 +1078,20 @@ class HacsRepository:
for treefile in self.tree:
self.treefiles.append(treefile.full_path)
except (AIOGitHubAPIException, HacsException) as exception:
if (
not retry
and self.ref is not None
and str(exception).startswith("GitHub returned 404")
):
# Handle tags/branches being deleted.
self.data.selected_tag = None
self.ref = self.version_to_download()
self.logger.warning(
"%s Selected version/branch %s has been removed, falling back to default",
self.string,
self.ref,
)
return await self.common_update_data(ignore_issues, force, True)
if not self.hacs.status.startup and not ignore_issues:
self.logger.error("%s %s", self.string, exception)
if not ignore_issues:

View File

@@ -3,8 +3,10 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Any
from homeassistant.helpers.issue_registry import async_create_issue, IssueSeverity
from homeassistant.loader import async_get_custom_components
from ..const import DOMAIN
from ..enums import HacsCategory, HacsDispatchEvent, HacsGitHubRepo, RepositoryFile
from ..exceptions import AddonRepositoryException, HacsException
from ..utils.decode import decode_content
@@ -36,13 +38,27 @@ class HacsIntegrationRepository(HacsRepository):
async def async_post_installation(self):
"""Run post installation steps."""
self.pending_restart = True
if self.data.config_flow:
if self.data.full_name != HacsGitHubRepo.INTEGRATION:
await self.reload_custom_components()
if self.data.first_install:
self.pending_restart = False
return
self.pending_restart = True
if self.pending_restart and self.hacs.configuration.experimental:
self.logger.debug("%s Creating restart_required issue", self.string)
async_create_issue(
hass=self.hacs.hass,
domain=DOMAIN,
issue_id=f"restart_required_{self.data.id}_{self.ref}",
is_fixable=True,
issue_domain=self.data.domain or DOMAIN,
severity=IssueSeverity.WARNING,
translation_key="restart_required",
translation_placeholders={
"name": self.display_name,
},
)
async def validate_repository(self):
"""Validate."""

View File

@@ -1,9 +1,13 @@
"""Sensor platform for HACS."""
from __future__ import annotations
from typing import TYPE_CHECKING
from homeassistant.components.sensor import SensorEntity
from homeassistant.core import callback
if TYPE_CHECKING:
from .base import HacsBase
from .const import DOMAIN
from .entity import HacsSystemEntity
from .enums import ConfigurationType
@@ -16,6 +20,10 @@ async def async_setup_platform(hass, _config, async_add_entities, _discovery_inf
async def async_setup_entry(hass, _config_entry, async_add_devices):
"""Setup sensor platform."""
hacs: HacsBase = hass.data.get(DOMAIN)
if hacs.configuration.experimental:
return
async_add_devices([HACSSensor(hacs=hass.data.get(DOMAIN))])

View File

@@ -53,5 +53,22 @@
}
}
}
},
"issues": {
"restart_required": {
"title": "Restart required",
"fix_flow": {
"step": {
"confirm_restart": {
"title": "Restart required",
"description": "Restart of Home Assistant is required to finish download/update of {name}, click submit to restart now."
}
}
}
},
"removed": {
"title": "Repository removed from HACS",
"description": "{name} has been removed from HACS for {reason} visit the [HACS Panel](/hacs/repository/{repositry_id}) to remove it."
}
}
}

View File

@@ -3,10 +3,11 @@ import asyncio
from datetime import datetime
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.util import json as json_util
from ..base import HacsBase
from ..enums import HacsDispatchEvent, HacsGitHubRepo
from ..enums import HacsDisabledReason, HacsDispatchEvent, HacsGitHubRepo
from ..repositories.base import TOPIC_FILTER, HacsManifest, HacsRepository
from .logger import LOGGER
from .path import is_safe
@@ -116,8 +117,21 @@ class HacsData:
async def restore(self):
"""Restore saved data."""
self.hacs.status.new = False
try:
hacs = await async_load_from_store(self.hacs.hass, "hacs") or {}
except HomeAssistantError:
hacs = {}
try:
repositories = await async_load_from_store(self.hacs.hass, "repositories") or {}
except HomeAssistantError as exception:
self.hacs.log.error(
"Could not read %s, restore the file from a backup - %s",
self.hacs.hass.config.path(".storage/hacs.repositories"),
exception,
)
self.hacs.disable_hacs(HacsDisabledReason.RESTORE)
return False
if not hacs and not repositories:
# Assume new install

File diff suppressed because one or more lines are too long

View File

@@ -21,7 +21,7 @@ def version_left_higher_then_right(left: str, right: str) -> bool | None:
and right_version.strategy != AwesomeVersionStrategy.UNKNOWN
):
return left_version > right_version
except (AwesomeVersionException, AttributeError):
except (AwesomeVersionException, AttributeError, KeyError):
pass
return None

View File

@@ -26,4 +26,4 @@ class Validator(ActionValidationBase):
if [ignore for ignore in IGNORED if ignore in line]:
continue
return
raise ValidationException("The repository does not have issues enabled")
raise ValidationException("The repository does not have images in the Readme file")

View File

@@ -9,7 +9,6 @@ from typing import TYPE_CHECKING
from homeassistant.core import HomeAssistant
from ..enums import HacsGitHubRepo
from ..repositories.base import HacsRepository
from .base import ActionValidationBase