Skip to content
Open
130 changes: 126 additions & 4 deletions docs/core/platform/repairs.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ from __future__ import annotations

import voluptuous as vol

from homeassistant import data_entry_flow
from homeassistant.components.repairs import ConfirmRepairFlow, RepairsFlow
from homeassistant.components.repairs import RepairsFlow, RepairsFlowResult
from homeassistant.core import HomeAssistant


Expand All @@ -69,14 +68,14 @@ class Issue1RepairFlow(RepairsFlow):

async def async_step_init(
self, user_input: dict[str, str] | None = None
) -> data_entry_flow.FlowResult:
) -> RepairsFlowResult:
"""Handle the first step of a fix flow."""

return await (self.async_step_confirm())

async def async_step_confirm(
self, user_input: dict[str, str] | None = None
) -> data_entry_flow.FlowResult:
) -> RepairsFlowResult:
"""Handle the confirm step of a fix flow."""
if user_input is not None:
return self.async_create_entry(title="", data={})
Expand All @@ -94,6 +93,108 @@ async def async_create_fix_flow(
return Issue1RepairFlow()
```

### Issues that can be repaired via entry/options/subentry reconfiguration or other repair flows.

Repair flows can forward issue fixes to config, options, subentry, or even different repair flows:

```python
import voluptuous as vol

from homeassistant import data_entry_flow
from homeassistant.components.repairs import FlowType, RepairsFlow, RepairsFlowResult
from homeassistant.config_entries import (
SOURCE_RECONFIGURE,
SubentryFlowContext,
SubentryFlowResult,
)
from homeassistant.core import HomeAssistant

class Issue1RepairFlow(RepairsFlow):
"""Handler for an issue fixing flow."""

async def async_step_init(
self, user_input: dict[str, str] | None = None
) -> RepairsFlowResult:
return await (self.async_step_confirm())

async def async_step_confirm(
self, user_input: dict[str, str] | None = None
) -> RepairsFlowResult:
"""Handle the confirm step of a fix flow."""
if user_input is not None:
next_flow: SubentryFlowResult = (
await self.hass.config_entries.subentries.async_init(
(self.data["entry_id"], "subentry_type"),
context=SubentryFlowContext(
subentry_id=self.data["subentry_id"],
source=SOURCE_RECONFIGURE,
),
)
)
return self.async_abort(
title="", data={},
next_flow=(
FlowType.CONFIG_SUBENTRIES_FLOW,
next_flow["flow_id"]
)
)

return self.async_show_form(
step_id="confirm",
data_schema=vol.Schema({})
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.
If using `next_flow` in the repair flow's `async_abort` it will be the responsiblity of the developer to [delete](#deleting_an_issue) the issue from the registry once the repair (i.e. config entry reconfigured) has been made.
Comment thread
iluvdata marked this conversation as resolved.
Outdated

#### Example `next_flow` options flow

```python
next_flow: ConfigFlowResult = (
await self.hass.config_entries.options.async_init(
self.data["entry_id"]
)
)
return self.async_create_entry(
title="", data={},
next_flow=(
FlowType.OPTIONS_FLOW,
next_flow["flow_id"]
)
)
```
Comment thread
iluvdata marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

#### Example `next_flow` repair flow

```python
from homeassistant import data_entry_flow
from homeassistant.components.repairs import FlowType, RepairsFlow, RepairsFlowResult, RepairsFlowManager, async_get

async def async_step_confirm(
self, user_input: dict[str, str] | None = None
) -> RepairsFlowResult:
"""Handle the confirm step of a fix flow."""
if user_input is not None:
repairs_flow_handler: RepairsFlowManager = async_get(self.hass)
next_flow: RepairsFlow = await repairs_flow_handler.async_init(
DOMAIN, # The domain of the integration containing the `is_fixable = True` issue with corresponding fix flow
data = {
"issue_id": "example_issue_id"
}
)

return self.async_create_entry(
title="", data={},
next_flow=(
FlowType.REPAIR_FLOW,
next_flow["flow_id"]
)
Comment thread
iluvdata marked this conversation as resolved.
)

```
> [!TIP]
> The `RepairsFlowManager` expects the `issue_id` to be passed via `data` as dictionary as with a key of `issue_id` as shown above.
>
> The `next_flow` argument in `async_abort` or `async_create_entry` expects a tuple: `tuple[homeassistant.components.repairs.FlowType, str]`.

## Issue life cycle

Expand All @@ -118,4 +219,25 @@ from homeassistant.helpers import issue_registry as ir

ir.async_delete_issue(hass, DOMAIN, "manual_migration")
```
### Repair flows using `next_flow`

Integration repair flows using `next_flow` will have to delete an issue once the repair is completed as the `RepairFlow.async_create_entry` will not remove the issue from the registry when `next_flow` is specified as an argument. Issues can be deleted in `config_flow.py` or in `async_setup_entry`:
Comment thread
iluvdata marked this conversation as resolved.
Outdated

```python
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Config entry reconfigure
if user_input is not None:
# Verify user_input is valid
if success:
ir.async_delete_issue(
self.hass,
DOMAIN,
"url_invalid",
)
return self.async_update_reload_and_abort(
self._get_reconfigure_entry(),
data=data,
)
```
Comment thread
iluvdata marked this conversation as resolved.