ha-deploy-kit 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/CHANGELOG.md +29 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/PKG-INFO +1 -1
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/pyproject.toml +1 -1
- ha_deploy_kit-0.1.4/src/ha_deploy_kit/ha/repairs_flow.py +56 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/ha/test_repairs_flow.py +18 -3
- ha_deploy_kit-0.1.2/src/ha_deploy_kit/ha/repairs_flow.py +0 -50
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/.coveragerc-ha +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/.github/workflows/release.yml +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/.github/workflows/validate.yml +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/.gitignore +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/LICENSE +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/README.md +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/docs/adopting.md +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/docs/configuration.md +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/docs/install.md +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/docs/releasing.md +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/backend_only/.env.example +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/backend_only/deploy.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/backend_only/deploy.sh +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/frontend_card/.env.example +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/frontend_card/deploy.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/frontend_card/deploy.sh +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/frontend_card/ha_adapter.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/synthetic_widget/deploy.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/examples/synthetic_widget/ha_adapter.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/__init__.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/cli.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/comparison.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/config.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/frontend.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/ha/__init__.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/ha/repairs_issue.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/ha/service.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/ha/serving.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/inventory.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/metadata/services.yaml.tmpl +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/metadata/strings.snippet.fixflow.json +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/metadata/strings.snippet.json +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/notify.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/settings.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/transport.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/conftest.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/ha/conftest.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/ha/test_example_adapters.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/ha/test_real_http_to_service.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/ha/test_repairs_issue.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/ha/test_service.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/ha/test_serving.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_cli.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_comparison.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_config.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_frontend.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_installed_smoke.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_inventory.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_multi_consumer.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_notify.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_packaging.py +0 -0
- {ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/tests/test_transport.py +0 -0
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.1.4 (2026-10-29)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- **ha**: Do not forward injected user_input into the restart confirm step
|
|
9
|
+
([`31fdb48`](https://github.com/latrekc-meta/ha-deploy-kit/commit/31fdb48b7c344ef0fb49b8459a58df54e3d7613c))
|
|
10
|
+
|
|
11
|
+
HA seeds the first fix-flow step's user_input with {"issue_id": ...} (RepairsFlowManager.async_init
|
|
12
|
+
-> data_entry_flow feeds it to async_step_init). async_step_init forwarded that into
|
|
13
|
+
async_step_confirm_restart, whose user_input-is-not-None branch then restarted Home Assistant the
|
|
14
|
+
instant the issue was opened -- no confirmation. Mirror HA's own ConfirmRepairFlow:
|
|
15
|
+
async_step_init delegates WITHOUT forwarding user_input, so the restart fires only on a real
|
|
16
|
+
submit. Add a regression test that opens the flow with {"issue_id": ...} and asserts no restart.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## v0.1.3 (2026-10-29)
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
- **ha**: Show restart confirmation without an empty schema
|
|
24
|
+
([`c6de7bb`](https://github.com/latrekc-meta/ha-deploy-kit/commit/c6de7bba87c0116d137a5cac918a5a050763ef59))
|
|
25
|
+
|
|
26
|
+
HA's Repairs frontend auto-submits a form that has an empty data schema, so
|
|
27
|
+
async_show_form(step_id=..., data_schema=vol.Schema({})) restarted Home Assistant the instant the
|
|
28
|
+
user opened the issue -- no confirmation. Show the form with no data schema (as in the proven
|
|
29
|
+
hand-rolled flow) so HA renders a confirmation that waits for an explicit submit. Add a regression
|
|
30
|
+
guard asserting data_schema is None.
|
|
31
|
+
|
|
32
|
+
|
|
4
33
|
## v0.1.2 (2026-10-29)
|
|
5
34
|
|
|
6
35
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ha-deploy-kit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: HA-free SSH deploy / compare / notify / optional-frontend toolkit for Home Assistant custom components
|
|
5
5
|
Project-URL: Homepage, https://github.com/latrekc-meta/ha-deploy-kit
|
|
6
6
|
Project-URL: Repository, https://github.com/latrekc-meta/ha-deploy-kit
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-deploy-kit"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.4"
|
|
8
8
|
description = "HA-free SSH deploy / compare / notify / optional-frontend toolkit for Home Assistant custom components"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Optional opt-in confirm-and-restart Repairs flow.
|
|
2
|
+
|
|
3
|
+
Opening the Repairs issue shows a confirmation dialog; the restart happens ONLY
|
|
4
|
+
when the user submits it. This mirrors Home Assistant's own ``ConfirmRepairFlow``:
|
|
5
|
+
``async_step_init`` delegates to the confirm step WITHOUT forwarding ``user_input``.
|
|
6
|
+
That matters because HA seeds the first step's ``user_input`` with
|
|
7
|
+
``{"issue_id": ...}`` (see repairs ``RepairsFlowManager.async_init``); forwarding it
|
|
8
|
+
would look like a submit and restart Home Assistant the instant the issue is
|
|
9
|
+
opened. No executable restart lives in the core engine; this flow is the single
|
|
10
|
+
opt-in place a consumer may wire it.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import TYPE_CHECKING, Any
|
|
16
|
+
|
|
17
|
+
import voluptuous as vol
|
|
18
|
+
from homeassistant.components.repairs import RepairsFlow
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from homeassistant.core import HomeAssistant
|
|
22
|
+
from homeassistant.data_entry_flow import FlowResult
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _RestartRequiredFixFlow(RepairsFlow):
|
|
26
|
+
"""Shows a confirmation dialog, then restarts only when the user submits it."""
|
|
27
|
+
|
|
28
|
+
async def async_step_init(
|
|
29
|
+
self, user_input: dict[str, Any] | None = None
|
|
30
|
+
) -> FlowResult:
|
|
31
|
+
# Do NOT forward user_input: HA seeds the first step with
|
|
32
|
+
# {"issue_id": ...}, which would look like a submit and restart on open.
|
|
33
|
+
return await self.async_step_confirm_restart()
|
|
34
|
+
|
|
35
|
+
async def async_step_confirm_restart(
|
|
36
|
+
self, user_input: dict[str, Any] | None = None
|
|
37
|
+
) -> FlowResult:
|
|
38
|
+
if user_input is not None:
|
|
39
|
+
await self.hass.services.async_call("homeassistant", "restart")
|
|
40
|
+
return self.async_create_entry(title="", data={})
|
|
41
|
+
return self.async_show_form(
|
|
42
|
+
step_id="confirm_restart", data_schema=vol.Schema({})
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def async_create_restart_fix_flow(
|
|
47
|
+
hass: HomeAssistant,
|
|
48
|
+
issue_id: str,
|
|
49
|
+
data: dict[str, Any] | None = None,
|
|
50
|
+
*,
|
|
51
|
+
expected_issue_id: str = "restart_required",
|
|
52
|
+
) -> RepairsFlow | None:
|
|
53
|
+
"""Return the opt-in restart fix flow, or ``None`` for other issue ids."""
|
|
54
|
+
if issue_id != expected_issue_id:
|
|
55
|
+
return None
|
|
56
|
+
return _RestartRequiredFixFlow()
|
|
@@ -6,17 +6,32 @@ from ha_deploy_kit.ha import async_create_restart_fix_flow
|
|
|
6
6
|
pytestmark = pytest.mark.ha
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
async def
|
|
9
|
+
async def test_opening_the_issue_shows_the_form_and_never_restarts(hass):
|
|
10
|
+
# HA seeds the first step's user_input with {"issue_id": ...} (see
|
|
11
|
+
# RepairsFlowManager.async_init). async_step_init must still only SHOW the
|
|
12
|
+
# confirmation dialog -- never restart on open.
|
|
10
13
|
calls = async_mock_service(hass, "homeassistant", "restart")
|
|
11
14
|
|
|
12
15
|
flow = async_create_restart_fix_flow(hass, "restart_required")
|
|
13
16
|
assert flow is not None
|
|
14
17
|
flow.hass = hass
|
|
15
18
|
|
|
16
|
-
shown = await flow.async_step_init()
|
|
19
|
+
shown = await flow.async_step_init({"issue_id": "restart_required"})
|
|
17
20
|
assert shown["type"] == "form"
|
|
18
21
|
assert shown["step_id"] == "confirm_restart"
|
|
19
|
-
assert len(calls) == 0 #
|
|
22
|
+
assert len(calls) == 0 # opening the issue must not restart
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def test_init_without_input_shows_the_form(hass):
|
|
26
|
+
calls = async_mock_service(hass, "homeassistant", "restart")
|
|
27
|
+
|
|
28
|
+
flow = async_create_restart_fix_flow(hass, "restart_required")
|
|
29
|
+
assert flow is not None
|
|
30
|
+
flow.hass = hass
|
|
31
|
+
|
|
32
|
+
shown = await flow.async_step_init()
|
|
33
|
+
assert shown["type"] == "form"
|
|
34
|
+
assert len(calls) == 0
|
|
20
35
|
|
|
21
36
|
|
|
22
37
|
async def test_restart_only_after_submitting_the_dialog(hass):
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"""Optional opt-in confirm-and-restart Repairs flow.
|
|
2
|
-
|
|
3
|
-
The restart happens ONLY after the user submits the confirmation dialog. Opening
|
|
4
|
-
the Repairs issue shows a dialog describing the restart; clicking submit is the
|
|
5
|
-
explicit confirmation. No executable restart lives in the core engine; this flow
|
|
6
|
-
is the single opt-in place a consumer may wire it.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
from typing import TYPE_CHECKING, Any
|
|
12
|
-
|
|
13
|
-
import voluptuous as vol
|
|
14
|
-
from homeassistant.components.repairs import RepairsFlow
|
|
15
|
-
|
|
16
|
-
if TYPE_CHECKING:
|
|
17
|
-
from homeassistant.core import HomeAssistant
|
|
18
|
-
from homeassistant.data_entry_flow import FlowResult
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class _RestartRequiredFixFlow(RepairsFlow):
|
|
22
|
-
"""Shows a confirmation dialog, then restarts only when the user submits it."""
|
|
23
|
-
|
|
24
|
-
async def async_step_init(
|
|
25
|
-
self, user_input: dict[str, Any] | None = None
|
|
26
|
-
) -> FlowResult:
|
|
27
|
-
return await self.async_step_confirm_restart(user_input)
|
|
28
|
-
|
|
29
|
-
async def async_step_confirm_restart(
|
|
30
|
-
self, user_input: dict[str, Any] | None = None
|
|
31
|
-
) -> FlowResult:
|
|
32
|
-
if user_input is None:
|
|
33
|
-
return self.async_show_form(
|
|
34
|
-
step_id="confirm_restart", data_schema=vol.Schema({})
|
|
35
|
-
)
|
|
36
|
-
await self.hass.services.async_call("homeassistant", "restart", blocking=False)
|
|
37
|
-
return self.async_create_entry(title="", data={})
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def async_create_restart_fix_flow(
|
|
41
|
-
hass: HomeAssistant,
|
|
42
|
-
issue_id: str,
|
|
43
|
-
data: dict[str, Any] | None = None,
|
|
44
|
-
*,
|
|
45
|
-
expected_issue_id: str = "restart_required",
|
|
46
|
-
) -> RepairsFlow | None:
|
|
47
|
-
"""Return the opt-in restart fix flow, or ``None`` for other issue ids."""
|
|
48
|
-
if issue_id != expected_issue_id:
|
|
49
|
-
return None
|
|
50
|
-
return _RestartRequiredFixFlow()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_deploy_kit-0.1.2 → ha_deploy_kit-0.1.4}/src/ha_deploy_kit/metadata/strings.snippet.fixflow.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|