Compare commits

...

11 Commits

Author SHA1 Message Date
Pascal Vizeli
c37b5effd7 Add music assistant to the builtin repositories (#5128)
* Add music assistant to the builtin repositories

* Fix tests

* Fix tests some more

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-06-21 12:17:21 +02:00
dependabot[bot]
ca7f3e8acb Bump ruff from 0.4.9 to 0.4.10 (#5143)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-21 09:27:10 +02:00
Stefan Agner
b0cdb91d5e Fix uninstall of add-on on fixup (#5142) 2024-06-21 08:54:46 +02:00
Mike Degatano
4829eb8ae1 Await uninstall of addon in fixup (#5141) 2024-06-20 21:50:45 +02:00
Mike Degatano
1bb814b793 Home Assistant watchdog attempts safe mode after max fails (#5124)
* Home Assistant watchdog attempts safe mode after max fails

* Remove duplicate line

* Refactor and logging change from feedback

* Update supervisor/misc/tasks.py

* Fix log text check in test

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-06-20 21:50:29 +02:00
dependabot[bot]
918fcb7d62 Bump sentry-sdk from 2.5.1 to 2.6.0 (#5140)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-20 11:39:26 +02:00
dependabot[bot]
bbfd899564 Bump setuptools from 70.0.0 to 70.1.0 (#5139)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-20 09:11:45 +02:00
dependabot[bot]
12c4d9da87 Bump urllib3 from 2.2.1 to 2.2.2 (#5138)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-18 07:52:04 +02:00
dependabot[bot]
6b4fd9b6b8 Bump ruff from 0.4.8 to 0.4.9 (#5137)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.8 to 0.4.9.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.4.8...v0.4.9)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-17 09:05:58 +02:00
dependabot[bot]
07c22f4a60 Bump codecov/codecov-action from 4.4.1 to 4.5.0 (#5136)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-14 09:27:41 +02:00
dependabot[bot]
252e1e2ac0 Bump actions/checkout from 4.1.6 to 4.1.7 (#5134)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.6...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-13 09:17:05 +02:00
14 changed files with 105 additions and 55 deletions

View File

@@ -53,7 +53,7 @@ jobs:
requirements: ${{ steps.requirements.outputs.changed }}
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
with:
fetch-depth: 0
@@ -92,7 +92,7 @@ jobs:
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
with:
fetch-depth: 0
@@ -178,7 +178,7 @@ jobs:
steps:
- name: Checkout the repository
if: needs.init.outputs.publish == 'true'
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Initialize git
if: needs.init.outputs.publish == 'true'
@@ -203,7 +203,7 @@ jobs:
timeout-minutes: 60
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Build the Supervisor
if: needs.init.outputs.publish != 'true'

View File

@@ -25,7 +25,7 @@ jobs:
name: Prepare Python dependencies
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python
id: python
uses: actions/setup-python@v5.1.0
@@ -67,7 +67,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.1.0
id: python
@@ -110,7 +110,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.1.0
id: python
@@ -153,7 +153,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Register hadolint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
@@ -168,7 +168,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.1.0
id: python
@@ -212,7 +212,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.1.0
id: python
@@ -256,7 +256,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.1.0
id: python
@@ -288,7 +288,7 @@ jobs:
name: Run tests Python ${{ needs.prepare.outputs.python-version }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.1.0
id: python
@@ -346,7 +346,7 @@ jobs:
needs: ["pytest", "prepare"]
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.1.0
id: python
@@ -373,4 +373,4 @@ jobs:
coverage report
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.4.1
uses: codecov/codecov-action@v4.5.0

View File

@@ -11,7 +11,7 @@ jobs:
name: Release Drafter
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
with:
fetch-depth: 0

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.6
uses: actions/checkout@v4.1.7
- name: Sentry Release
uses: getsentry/action-release@v1.7.0
env:

View File

@@ -22,8 +22,8 @@ pyudev==0.24.3
PyYAML==6.0.1
requests==2.32.3
securetar==2024.2.1
sentry-sdk==2.5.1
setuptools==70.0.0
sentry-sdk==2.6.0
setuptools==70.1.0
voluptuous==0.14.2
dbus-fast==2.21.3
typing_extensions==4.12.2

View File

@@ -6,7 +6,7 @@ pytest-asyncio==0.23.6
pytest-cov==5.0.0
pytest-timeout==2.3.1
pytest==8.2.2
ruff==0.4.8
ruff==0.4.10
time-machine==2.14.1
typing_extensions==4.12.2
urllib3==2.2.1
urllib3==2.2.2

View File

@@ -174,17 +174,6 @@ class Tasks(CoreSysAttributes):
self._cache[HASS_WATCHDOG_API_FAILURES] = 0
return
# Give up after 5 reanimation failures in a row. Supervisor cannot fix this issue.
reanimate_fails = self._cache.get(HASS_WATCHDOG_REANIMATE_FAILURES, 0)
if reanimate_fails >= HASS_WATCHDOG_MAX_REANIMATE_ATTEMPTS:
if reanimate_fails == HASS_WATCHDOG_MAX_REANIMATE_ATTEMPTS:
_LOGGER.critical(
"Watchdog cannot reanimate Home Assistant Core, failed all %s attempts.",
reanimate_fails,
)
self._cache[HASS_WATCHDOG_REANIMATE_FAILURES] += 1
return
# Init cache data
api_fails = self._cache.get(HASS_WATCHDOG_API_FAILURES, 0)
@@ -195,16 +184,38 @@ class Tasks(CoreSysAttributes):
_LOGGER.warning("Watchdog missed an Home Assistant Core API response.")
return
_LOGGER.error(
"Watchdog missed %s Home Assistant Core API responses in a row. Restarting Home Assistant Core API!",
HASS_WATCHDOG_MAX_API_ATTEMPTS,
)
# After 5 reanimation attempts switch to safe mode. If that fails, give up
reanimate_fails = self._cache.get(HASS_WATCHDOG_REANIMATE_FAILURES, 0)
if reanimate_fails > HASS_WATCHDOG_MAX_REANIMATE_ATTEMPTS:
return
if safe_mode := reanimate_fails == HASS_WATCHDOG_MAX_REANIMATE_ATTEMPTS:
_LOGGER.critical(
"Watchdog cannot reanimate Home Assistant Core, failed all %s attempts. Restarting into safe mode",
reanimate_fails,
)
else:
_LOGGER.error(
"Watchdog missed %s Home Assistant Core API responses in a row. Restarting Home Assistant Core!",
HASS_WATCHDOG_MAX_API_ATTEMPTS,
)
try:
await self.sys_homeassistant.core.restart()
if safe_mode:
await self.sys_homeassistant.core.rebuild(safe_mode=True)
else:
await self.sys_homeassistant.core.restart()
except HomeAssistantError as err:
_LOGGER.error("Home Assistant watchdog reanimation failed!")
if reanimate_fails == 0:
if reanimate_fails == 0 or safe_mode:
capture_exception(err)
if safe_mode:
_LOGGER.critical(
"Safe mode restart failed. Watchdog cannot bring Home Assistant online."
)
else:
_LOGGER.error("Home Assistant watchdog reanimation failed!")
self._cache[HASS_WATCHDOG_REANIMATE_FAILURES] = reanimate_fails + 1
else:
self._cache[HASS_WATCHDOG_REANIMATE_FAILURES] = 0

View File

@@ -26,7 +26,7 @@ class FixupAddonExecuteRemove(FixupBase):
# Remove addon
_LOGGER.info("Remove addon: %s", reference)
try:
addon.uninstall()
await addon.uninstall(remove_config=False)
except AddonsError as err:
_LOGGER.error("Could not remove %s due to %s", reference, err)
raise ResolutionFixupError() from None

View File

@@ -8,11 +8,13 @@ from .const import StoreType
URL_COMMUNITY_ADDONS = "https://github.com/hassio-addons/repository"
URL_ESPHOME = "https://github.com/esphome/home-assistant-addon"
URL_MUSIC_ASSISTANT = "https://github.com/music-assistant/home-assistant-addon"
BUILTIN_REPOSITORIES = {
StoreType.CORE,
StoreType.LOCAL,
URL_COMMUNITY_ADDONS,
URL_ESPHOME,
URL_MUSIC_ASSISTANT,
}
# pylint: disable=no-value-for-parameter

View File

@@ -0,0 +1,5 @@
{
"name": "Music Assistant",
"url": "https://github.com/music-assistant/core",
"maintainer": "Music Assistant <marcelveldt@users.noreply.github.com>"
}

View File

@@ -46,7 +46,7 @@ async def test_watchdog_homeassistant_api(
restart.assert_called_once()
assert "Watchdog missed an Home Assistant Core API response." not in caplog.text
assert (
"Watchdog missed 2 Home Assistant Core API responses in a row. Restarting Home Assistant Core API!"
"Watchdog missed 2 Home Assistant Core API responses in a row. Restarting Home Assistant Core!"
in caplog.text
)
@@ -109,31 +109,48 @@ async def test_watchdog_homeassistant_api_reanimation_limit(
HomeAssistantAPI, "check_api_state", return_value=False
), patch.object(
HomeAssistantCore, "restart", side_effect=(err := HomeAssistantError())
) as restart:
) as restart, patch.object(
HomeAssistantCore, "rebuild", side_effect=err
) as rebuild:
for _ in range(5):
await tasks._watchdog_homeassistant_api()
restart.assert_not_called()
await tasks._watchdog_homeassistant_api()
restart.assert_called_once()
restart.assert_called_once_with()
assert "Home Assistant watchdog reanimation failed!" in caplog.text
rebuild.assert_not_called()
restart.reset_mock()
capture_exception.assert_called_once_with(err)
# Next time it should try safe mode
caplog.clear()
await tasks._watchdog_homeassistant_api()
rebuild.assert_not_called()
await tasks._watchdog_homeassistant_api()
rebuild.assert_called_once_with(safe_mode=True)
restart.assert_not_called()
assert "Watchdog missed an Home Assistant Core API response." not in caplog.text
assert "Watchdog found a problem with Home Assistant API!" not in caplog.text
assert (
"Watchdog cannot reanimate Home Assistant Core, failed all 5 attempts."
"Watchdog cannot reanimate Home Assistant Core, failed all 5 attempts. Restarting into safe mode"
in caplog.text
)
assert (
"Safe mode restart failed. Watchdog cannot bring Home Assistant online."
in caplog.text
)
# After safe mode has failed too, no more restart attempts
rebuild.reset_mock()
caplog.clear()
await tasks._watchdog_homeassistant_api()
assert "Watchdog missed an Home Assistant Core API response." in caplog.text
caplog.clear()
await tasks._watchdog_homeassistant_api()
restart.assert_not_called()
assert not caplog.text
restart.assert_not_called()
rebuild.assert_not_called()

View File

@@ -163,6 +163,7 @@ async def test_preinstall_valid_repository(
assert store_manager.get("local").validate()
assert store_manager.get("a0d7b954").validate()
assert store_manager.get("5c53de3b").validate()
assert store_manager.get("d5369777").validate()
@pytest.mark.parametrize("use_update", [True, False])

View File

@@ -39,11 +39,11 @@ async def test_default_load(coresys: CoreSys):
):
await store_manager.load()
assert len(store_manager.all) == 4
assert len(store_manager.all) == 5
assert isinstance(store_manager.get("core"), Repository)
assert isinstance(store_manager.get("local"), Repository)
assert len(store_manager.repository_urls) == 2
assert len(store_manager.repository_urls) == 3
assert (
"https://github.com/hassio-addons/repository" in store_manager.repository_urls
)
@@ -51,6 +51,11 @@ async def test_default_load(coresys: CoreSys):
"https://github.com/esphome/home-assistant-addon"
in store_manager.repository_urls
)
assert (
"https://github.com/music-assistant/home-assistant-addon"
in store_manager.repository_urls
)
# NOTE: When adding new stores, make sure to add it to tests/fixtures/addons/git/
assert refresh_cache_calls == {"local_ssh", "local_example", "core_samba"}
@@ -77,11 +82,11 @@ async def test_load_with_custom_repository(coresys: CoreSys):
):
await store_manager.load()
assert len(store_manager.all) == 5
assert len(store_manager.all) == 6
assert isinstance(store_manager.get("core"), Repository)
assert isinstance(store_manager.get("local"), Repository)
assert len(store_manager.repository_urls) == 3
assert len(store_manager.repository_urls) == 4
assert (
"https://github.com/hassio-addons/repository" in store_manager.repository_urls
)
@@ -89,6 +94,10 @@ async def test_load_with_custom_repository(coresys: CoreSys):
"https://github.com/esphome/home-assistant-addon"
in store_manager.repository_urls
)
assert (
"https://github.com/music-assistant/home-assistant-addon"
in store_manager.repository_urls
)
assert "http://example.com" in store_manager.repository_urls
@@ -105,11 +114,11 @@ async def test_load_from_core_config(coresys: CoreSys):
), patch("pathlib.Path.exists", return_value=True):
await coresys.store.load()
assert len(coresys.store.all) == 5
assert len(coresys.store.all) == 6
assert isinstance(coresys.store.get("core"), Repository)
assert isinstance(coresys.store.get("local"), Repository)
assert len(coresys.store.repository_urls) == 3
assert len(coresys.store.repository_urls) == 4
assert (
"https://github.com/hassio-addons/repository" in coresys.store.repository_urls
)
@@ -117,6 +126,10 @@ async def test_load_from_core_config(coresys: CoreSys):
"https://github.com/esphome/home-assistant-addon"
in coresys.store.repository_urls
)
assert (
"https://github.com/music-assistant/home-assistant-addon"
in coresys.store.repository_urls
)
assert "http://example.com" in coresys.store.repository_urls
assert coresys.config.addons_repositories == []
@@ -243,12 +256,12 @@ async def test_install_unavailable_addon(
async def test_reload(coresys: CoreSys):
"""Test store reload."""
await coresys.store.load()
assert len(coresys.store.all) == 4
assert len(coresys.store.all) == 5
with patch.object(GitRepo, "pull") as git_pull:
await coresys.store.reload()
assert git_pull.call_count == 3
assert git_pull.call_count == 4
async def test_addon_version_timestamp(coresys: CoreSys, install_addon_example: Addon):

View File

@@ -49,12 +49,13 @@ async def test_repository_validate(repo_list: list[str], valid: bool):
"""Test repository list validate."""
if valid:
processed = repositories(repo_list)
assert len(processed) == 4
assert len(processed) == 5
assert set(repositories(repo_list)) == {
"core",
"local",
"https://github.com/hassio-addons/repository",
"https://github.com/esphome/home-assistant-addon",
"https://github.com/music-assistant/home-assistant-addon",
}
else:
with pytest.raises(Invalid):