Introduce Home Assistant Labs#156840
Conversation
|
Hey there @home-assistant/core, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
|
|
||
| # Update storage | ||
| labs_data.data["features"][feature_id] = enabled | ||
| await labs_data.store.async_save(labs_data.data) |
There was a problem hiding this comment.
Should we use the delayed save feature on the Store class async_delay_save? The user could click around causing multiple calls to this function in short succession.
There was a problem hiding this comment.
I've considered. It doesn't change as much + there is a process involved of confirmation and possible backups. We don't have many options and quick toggles anymore.
However, integration can respond to a change, so saving the state directly might avoid things like migrations issues or any other changes integration make on turning on/off the labs feature.
I've therefore opted to leave it as an immediate save.
There was a problem hiding this comment.
What would the migration issues or other issues be? That would be a bug in the base storage class.
There was a problem hiding this comment.
Not about the migration of the storage of Labs itself, it is about the integration that can do thing based on the change of this flag. It thus may have repercussions beyond this integration.
There was a problem hiding this comment.
I don't understand what this has to do with the Store. The Store is used to save data on file. The source of truth during runtime is the labs_data.data attribute.
There was a problem hiding this comment.
Agreed, but it are "experimental" features one is enabling; I feel that a direct write is more warranted, as we don't know or control what is happening next as a result out of this. It might be a full crash, migrations, many other things.
Besides that, considering this is not a high volume feature (at least not right now) and not a usual toggle to make (need confirmation, backups completion in between) it is less likely to need debouncing.
There was a problem hiding this comment.
Pull Request Overview
This PR introduces Home Assistant Labs, a new system integration that provides a standardized way for integrations to expose preview features that users can opt into. The Labs system allows integrations to define preview features in their manifest.json, which are then surfaced through a WebSocket API and can be managed by users via the UI. The implementation includes comprehensive test coverage and an example preview feature in the kitchen_sink integration that demonstrates creating repair issues when enabled.
Key changes:
- New Labs integration with WebSocket API for listing and updating preview features
- Support for preview features in integration manifests with URLs for feedback, documentation, and issue reporting
- Storage system to persist enabled preview feature states
- Event system (
labs_updated) to notify integrations when preview features are toggled - Example implementation in
kitchen_sinkintegration showing repair issue creation
Reviewed Changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| homeassistant/components/labs/init.py | Core Labs integration with storage, WebSocket handlers, and preview feature scanning |
| homeassistant/components/labs/const.py | Constants, data classes, and type definitions for Labs |
| homeassistant/components/labs/manifest.json | Labs integration manifest |
| homeassistant/components/labs/strings.json | Translation strings for Labs UI |
| homeassistant/components/kitchen_sink/init.py | Example implementation showing preview feature event handling and repair issue creation |
| homeassistant/components/kitchen_sink/manifest.json | Added preview_features definition with URLs |
| homeassistant/components/kitchen_sink/strings.json | Translation strings for preview feature and repair issue |
| homeassistant/generated/labs.py | Auto-generated file containing preview feature definitions from manifests |
| homeassistant/loader.py | Added preview_features property to Integration class |
| homeassistant/bootstrap.py | Added labs to Stage 0 integrations and default integrations |
| script/hassfest/labs.py | Script to generate and validate preview features from manifests |
| script/hassfest/main.py | Added labs module to hassfest processing |
| script/hassfest/manifest.py | Added preview_features validation to manifest schema |
| script/hassfest/translations.py | Added preview_features translation schema |
| script/hassfest/quality_scale.py | Exempted labs from quality scale requirements |
| script/hassfest/dependencies.py | Added labs to allowed components and circular dependency exemptions |
| script/json_schemas/manifest_schema.json | JSON schema for preview_features in manifests |
| tests/components/labs/test_init.py | Comprehensive tests for Labs setup and storage |
| tests/components/labs/test_websocket_api.py | Extensive WebSocket API tests covering all commands and scenarios |
| tests/components/labs/conftest.py | Test fixtures for Labs tests |
| tests/components/kitchen_sink/test_init.py | Tests for preview feature integration with repairs |
| CODEOWNERS | Added Labs integration ownership |
| (preview_feature.domain, preview_feature.preview_feature) | ||
| in labs_data.data["preview_feature_status"] | ||
| ) | ||
| for preview_feature_key, preview_feature in labs_data.preview_features.items() |
There was a problem hiding this comment.
Use dict.values() instead.
| await hass.async_block_till_done() | ||
|
|
||
| ws_client = await hass_ws_client(hass) | ||
| if preview_feature_enabled: |
There was a problem hiding this comment.
If all of the test code and all of the assertion code is different, using parameters doesn't make sense.
Just make a fixture for the setup code instead to reuse that in two different tests.
|
|
||
| async def test_async_setup(hass: HomeAssistant) -> None: | ||
| """Test the Labs integration setup.""" | ||
| assert await async_setup(hass, {}) |
There was a problem hiding this comment.
We don't set up integrations like this in tests. Use async_setup_component.
|
|
||
| # Subscribe to labs feature updates for kitchen_sink preview repair | ||
| @callback | ||
| def _async_labs_updated(event: Event[EventLabsUpdatedData]) -> None: |
There was a problem hiding this comment.
I wonder if this API could be simplified a bit by creating a helper function to create this listener function.
I'm thinking of something similar to the one below.
entry.async_on_unload(
preview_features.async_listen(
domain="kitchen_sink",
preview_feature="special_repair",
listener=lambda: _async_update_special_repair(hass)
)
)This way, the integration author does not have to wonder whether Futures Lab uses the event bus and what the message format is.
This will slightly extend the existing public API we currently have.
async_is_preview_feature_enabled(hass, DOMAIN, "special_repair"):There was a problem hiding this comment.
Yeah, we tend to avoid using core events nowadays for things that aren't user facing.
| def _async_labs_updated(event: Event[EventLabsUpdatedData]) -> None: | ||
| """Handle labs feature update event.""" | ||
| if ( | ||
| event.data["domain"] == "kitchen_sink" |
There was a problem hiding this comment.
Can we use DOMAIN const here?
There was a problem hiding this comment.
we don't have to, it is typed already.
There was a problem hiding this comment.
oh sorry the domain constant using kitchen_sink; yeah sure 👍
|
|
||
|
|
||
| @callback | ||
| def async_is_preview_feature_enabled( |
There was a problem hiding this comment.
Can we add a function that retrieves all statuses for a given domain? I guess some component authors will want to display some warnings or something when at least one flag is enabled, or include information about the flag status in diagnostic data?
There was a problem hiding this comment.
If the need occurs we can evaluate that; it is a good idea, but I think we need a few actual needs and use cases before adding stuff like that.
There was a problem hiding this comment.
It would probably be worth adding information about enabled parameters for all integrations when it is available in the core. This way we already have the first function consumer.
Proposed change
This PR introduces Home Assistant Labs.
A feature that allows integrations to expose preview features that an user can opt-in to.
It provides a standardized way to ship preview features that users can opt into before they become standard / generally available. Labs preview features are critical bug free, fully functional features that are being refined through real-world usage and feedback before becoming standard in Home Assistant. They differ from beta testing, which evaluates release stability.
They differ from betas. A beta test, tests for general stability of Home Assistant, while these previews are aimed at validating and iterating new features that might not have yet reached the envisioned feature set.
Demo video:
CleanShot.2025-11-18.at.22.53.03.mp4
A small example implementation is provided in the
kitchen_sinkintegration.Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: