Skip to content

Surface automation required-groups and stop hiding their members as advanced#1908

Merged
bdraco merged 4 commits into
mainfrom
automation-required-groups
Jul 9, 2026
Merged

Surface automation required-groups and stop hiding their members as advanced#1908
bdraco merged 4 commits into
mainfrom
automation-required-groups

Conversation

@bdraco

@bdraco bdraco commented Jul 8, 2026

Copy link
Copy Markdown
Member

What does this implement/fix?

The automation editor writes - sensor.in_range: {id: ...} with no above or below, and validation fails with "Must contain at least one of above, below." The generated condition definition marks both fields advanced: true, so the structured editor never shows them; the schema bundle drops the cv.has_at_least_one_key(...) wrapper entirely, so the sync script had no way to see the constraint.

The sync script now reads the live action/condition registries after the component import sweep and reuses the existing cv.has_*_one_key introspection the component catalog got in #924: matching bodies gain required_groups, their members are promoted off advanced, and the descriptions get the same "set at least one of" hint. Seven registry entries carry such groups; the if action's groups name control flow keys (then, condition) that are stripped from config_entries, so it is filtered out and six definitions change: sensor.in_range, number.in_range, deep_sleep.enter, homeassistant.service, homeassistant.action, ota.http_request.flash. AutomationAction / AutomationCondition gain a required_groups model field so the constraint reaches the wire; the slim index is unchanged.

Notes for review: promoting all group members also surfaces the deprecated service alias on homeassistant.service / homeassistant.action, matching how the component path treats constraint members. Triggers are out of scope; sensor.on_value_range already shows above / below and only lacks the hint, and triggers are not registry backed.

Related issue or feature (if applicable):

Types of changes

  • Bugfix (non-breaking change which fixes an issue) — bugfix
  • New feature (non-breaking change which adds functionality) — new-feature
  • Enhancement to an existing feature — enhancement
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) — breaking-change
  • Refactor (no behaviour change) — refactor
  • Documentation only — docs
  • Maintenance / chore — maintenance
  • CI / workflow change — ci
  • Dependencies bump — dependencies

Frontend coordination

Checklist

  • The code change is tested and works locally.
  • Pre-commit hooks pass (ruff, codespell, yaml/json/python checks).
  • Tests have been added or updated under tests/ where applicable.
  • components.index.json / definitions/components/*.json have not been hand-edited (regenerate via script/sync_components.py if a sync is needed).
  • Architecture-level changes are reflected in docs/ARCHITECTURE.md and/or docs/API.md.

@codspeed-hq

codspeed-hq Bot commented Jul 8, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 27 untouched benchmarks


Comparing automation-required-groups (68acad1) with main (0e58546)

Open in CodSpeed

@bdraco

bdraco commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@esphbot review

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.58%. Comparing base (0e58546) to head (68acad1).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1908   +/-   ##
=======================================
  Coverage   99.58%   99.58%           
=======================================
  Files         239      239           
  Lines       19361    19363    +2     
=======================================
+ Hits        19280    19282    +2     
  Misses         81       81           
Flag Coverage Δ
py3.12 99.54% <100.00%> (+<0.01%) ⬆️
py3.14 99.58% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
esphome_device_builder/models/automations.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@esphbot

esphbot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@bdraco: @esphbot review

Reviewed. Clean bugfix. Reuses #924 constraint introspection for live registries. if control-flow group correctly filtered. Tests thorough, 100% coverage. One non-blocking nit: action stays required:true inside the exactly-one group on homeassistant.service/action — confirm frontend #1153 handles required-member-in-group. Approving.

@esphbot

esphbot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Previous review — superseded by a newer review below.

@esphbot esphbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@bdraco bdraco marked this pull request as ready for review July 9, 2026 00:09
Copilot AI review requested due to automatic review settings July 9, 2026 00:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the automations catalog generation so action/condition schemas can surface cross-field “must set one of …” constraints (from live ESPHome registries) and ensures required-choice fields aren’t hidden behind the “Advanced” section, fixing invalid YAML output in the structured automation editor.

Changes:

  • Introspect ESPHome’s live automation action/condition registries to extract cv.has_*_one_key(...) constraints and stamp them into generated automation bodies as required_groups.
  • Promote required-group member fields off advanced and annotate their descriptions with “set at least/exactly one of …” hints.
  • Extend automation models/docs and add tests covering registry group extraction, catalog stamping, and served body payloads.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/test_sync_components_required_groups.py Adds tests for extracting required-groups from vol.All chains and from (fake/live) ESPHome automation registries.
tests/test_automations_sync.py Adds sync tests ensuring registry-provided required groups are emitted into automation bodies and that grouped fields are no longer advanced.
tests/test_automations_get_bodies.py Ensures the shipped sensor.in_range body is served with required_groups and non-advanced group members.
script/sync_components.py Implements live registry introspection, required-group extraction, and wiring into automations generation.
esphome_device_builder/models/automations.py Adds required_groups to AutomationAction / AutomationCondition wire models.
esphome_device_builder/definitions/automations/conditions/sensor.in_range.json Removes advanced from above/below, adds required_groups, and injects the “set at least one of” hint.
esphome_device_builder/definitions/automations/conditions/number.in_range.json Same required-group + advanced demotion + hint treatment for number range conditions.
esphome_device_builder/definitions/automations/actions/ota.http_request.flash.json Adds required_groups for md5 vs md5_url, promotes them off advanced, and injects the hint.
esphome_device_builder/definitions/automations/actions/homeassistant.service.json Adds required_groups for service vs action and promotes the alias field off advanced.
esphome_device_builder/definitions/automations/actions/homeassistant.action.json Same as above for the homeassistant.action entry.
esphome_device_builder/definitions/automations/actions/deep_sleep.enter.json Adds a none_or_all required group for until + time_id and annotates/promotes accordingly.
docs/API.md Documents required_groups on automations action/condition bodies and the “never advanced” constraint-member rule.

Comment thread script/sync_components.py Outdated
Comment on lines +7197 to +7200
required_groups = _automation_required_groups(group_index, qualified, config_entries)
if required_groups:
config_entries = _promote_constraint_members(config_entries, required_groups)
entry = {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 68acad1; the post-pass applier now clears required on every group member.

Comment thread script/sync_components.py Outdated
@bdraco

bdraco commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

Addressed the suggestion in 68acad1: group members now drop per-field required at the generator level, since the group is the requirement and the bundle's Required on the preferred alias was the artifact. Also folded the stamping into a single post-pass applier and brought the branch up to date with main.

@esphbot review

@bdraco

bdraco commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

@esphbot review

@esphbot

esphbot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

PR Review — Surface automation required-groups and stop hiding their members as advanced

Clean, well-scoped bugfix — merge-ready. Verified against the branch HEAD; the prior review's one open suggestion is now resolved.

Strengths:

  • Reuses the [Bug] “Advanced Settings” are sometimes absolutely necessary #924 constraint-introspection machinery instead of a parallel path: collect_at's inner closure is lifted to a shared module-level _groups_in_all_chain, used by both the schema-chain walk and the new live-registry read (_collect_automation_registry_groups).
  • Refactored to a single post-pass applier (_apply_automation_required_groups) run after _dedupe_by_id, so each unique action/condition id is stamped once — cleaner than the per-converter application in the first commit.
  • Control-flow group filtering is correct and tested: if's then/condition group is dropped because its keys aren't in config_entries (test_build_automations_drops_groups_over_non_form_keys).
  • required_groups reuses the existing RequiredGroup model with default_factory=list, so older bodies deserialize cleanly — backward compatible.
  • The earlier required:true-on-group-member concern (Copilot + prior review suggestion Add section config API and user preferences #1) is fixed: members now drop per-field required and advanced, then get the constraint hint. Confirmed in the shipped homeassistant.service.json/homeassistant.action.json.

Verification:

  • 92 tests pass across test_automations_sync.py, test_automations_get_bodies.py, test_sync_components_required_groups.py.
  • Shipped JSON for all six changed definitions inspected: action/service no longer carry required, group members no longer advanced.
  • Docs (API.md) and model (AutomationAction/AutomationCondition) updated; frontend coordination flagged ([Bug] Area not displayed in new ESPHome Device Builder Preview (Templates) #1153).

No blocking issues.



Checklist

  • Model change reuses existing type, backward compatible (default_factory)
  • No duplicated introspection path (_groups_in_all_chain shared)
  • required cleared on group members (prior suggestion resolved)
  • Control-flow keys filtered out of groups
  • Generated definitions regenerated, not hand-edited
  • Test coverage for new branches and edge cases (92 pass)
  • Docs updated (API.md)

Automated review by Kōan (Claude) HEAD=68acad1 3 min 41s

@esphbot esphbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

@bdraco bdraco merged commit e1e5844 into main Jul 9, 2026
21 checks passed
@bdraco bdraco deleted the automation-required-groups branch July 9, 2026 03:28
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

bugfix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automation editor cannot set sensor.in_range above/below, producing invalid YAML

3 participants