Skip to content
Open
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
22 changes: 21 additions & 1 deletion custom_components/hacs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
async_delete_issue,
async_get as async_get_issue_registry,
)
from homeassistant.loader import Integration
from homeassistant.util import dt

Expand Down Expand Up @@ -596,9 +601,24 @@ async def async_register_repository(

self.repositories.register(repository, default)

@callback
def async_delete_stale_restart_issues(self) -> None:
"""Delete restart_required issues left over from a previous run.

The issues are created when a download requires a restart to take
effect. Reaching this point means Home Assistant has restarted, so any
such issue from a previous run is resolved and its entry would
otherwise be kept in the issue registry forever.
"""
issue_registry = async_get_issue_registry(self.hass)
for issue in list(issue_registry.issues.values()):
if issue.domain == DOMAIN and issue.issue_id.startswith("restart_required_"):
async_delete_issue(self.hass, DOMAIN, issue.issue_id)

async def startup_tasks(self, _=None) -> None:
"""Tasks that are started after setup."""
self.set_stage(HacsStage.STARTUP)
self.async_delete_stale_restart_issues()
await self.async_load_hacs_from_github()

if critical := await async_load_from_store(self.hass, "critical"):
Expand Down
43 changes: 43 additions & 0 deletions tests/hacsbase/test_hacs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# pylint: disable=missing-module-docstring, missing-function-docstring
from homeassistant.helpers import issue_registry as ir
import pytest

from custom_components.hacs.base import HacsRepositories
from custom_components.hacs.const import DOMAIN
from custom_components.hacs.enums import HacsCategory


Expand Down Expand Up @@ -57,3 +59,44 @@ async def test_add_remove_repository(hacs, repository, tmpdir):

# Verify second removal does not raise
hacs.repositories.unregister(repository)


async def test_delete_stale_restart_issues(hacs):
issue_registry = ir.async_get(hacs.hass)

ir.async_create_issue(
hass=hacs.hass,
domain=DOMAIN,
issue_id="restart_required_1337_tags/1.0.0",
is_fixable=True,
severity=ir.IssueSeverity.WARNING,
translation_key="restart_required",
)
ir.async_create_issue(
hass=hacs.hass,
domain=DOMAIN,
issue_id="removed_1337",
is_fixable=False,
severity=ir.IssueSeverity.WARNING,
translation_key="removed",
)
ir.async_create_issue(
hass=hacs.hass,
domain="other",
issue_id="restart_required_1337_tags/1.0.0",
is_fixable=False,
severity=ir.IssueSeverity.WARNING,
translation_key="restart_required",
)

hacs.async_delete_stale_restart_issues()

# The restart has already happened, so the issue is no longer relevant
assert issue_registry.async_get_issue(DOMAIN, "restart_required_1337_tags/1.0.0") is None

# Issues of other types, and issues from other domains, are left alone
assert issue_registry.async_get_issue(DOMAIN, "removed_1337") is not None
assert issue_registry.async_get_issue("other", "restart_required_1337_tags/1.0.0") is not None

# Safe to run when there is nothing to delete
hacs.async_delete_stale_restart_issues()
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tests/hacsbase/test_hacs.py::test_delete_stale_restart_issues": {
"https://api.github.com/repos/hacs/integration": 1,
"https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1,
"https://api.github.com/repos/hacs/integration/contents/hacs.json": 1,
"https://api.github.com/repos/hacs/integration/git/trees/main": 1,
"https://api.github.com/repos/hacs/integration/releases": 1
}
}