Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ff19dfb
Add device class sync workflow comparing constants against HA
zigpy-review-bot Jul 3, 2026
97b39fd
Drop homeassistant from testing extras
zigpy-review-bot Jul 3, 2026
6050721
Add --write mode to compare_constants for auto-syncing
zigpy-review-bot Jul 3, 2026
4d9713f
Open a PR from the device class sync workflow
zigpy-review-bot Jul 3, 2026
99d6f11
Replace compare_constants with a verbatim HA syncer
zigpy-review-bot Jul 3, 2026
b4658ac
Sync device classes against HA Core dev and open a PR
zigpy-review-bot Jul 3, 2026
590810a
Add UnitOfDensity/UnitOfRatio and a backwards-compat unit constants s…
zigpy-review-bot Jul 3, 2026
a7b7c42
Drop zha-quirks from the sync workflow
zigpy-review-bot Jul 3, 2026
3970f37
Handle enums HA removes and anchor new-enum insertion
zigpy-review-bot Jul 3, 2026
60ad061
Update tools/README for the sync tool's current behavior
zigpy-review-bot Jul 3, 2026
b268441
Fix sync_constants docstring contradiction on removal
zigpy-review-bot Jul 3, 2026
8632808
Harden sync workflow and enum removal after review
zigpy-review-bot Jul 3, 2026
f09bd34
Drop the ruff format step and summarise changes in the PR body
zigpy-review-bot Jul 3, 2026
b8b6444
Correct sync docs and a units.py comment
zigpy-review-bot Jul 3, 2026
369c4cf
Report per-enum member and value changes in the sync summary
zigpy-review-bot Jul 3, 2026
6922dcf
Set pipefail in the sync step so a tool failure fails the run
zigpy-review-bot Jul 3, 2026
3b356b9
Address PR review: pin Python >=3.14.2 and simplify app-user step
zigpy-review-bot Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/workflows/sync-device-classes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Sync device classes from Home Assistant

# Copies ZHA's local copies of Home Assistant enums (unit enums, device class /
# mode enums) verbatim from Home Assistant's `dev` branch via
# `tools/sync_constants.py`, then opens/updates a single pull request with the
# result. The PR always targets the `sync/device-classes` branch, so each run
# updates the same PR rather than opening new ones.

on:
workflow_dispatch:
schedule:
- cron: "45 6 * * *"

permissions:
contents: read

# Serialise runs so a manual dispatch can't race the scheduled one on the
# shared sync/device-classes branch.
concurrency:
group: sync-device-classes
cancel-in-progress: false

jobs:
sync:
name: Sync device classes
runs-on: ubuntu-latest
if: github.repository == 'zigpy/zha'
steps:
# Uses a GitHub App so the pull request is authored by the bot account and
# triggers CI (a PR opened with the default GITHUB_TOKEN would not). The App
# ID / private key must be configured as a repository variable and secret.
- name: Generate a token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ vars.SYNC_APP_ID }}
private-key: ${{ secrets.SYNC_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write

- name: Get the app user id
id: app-user
run: |
user_id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)
echo "user-id=$user_id" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Checkout ZHA
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
token: ${{ steps.app-token.outputs.token }}

- name: Checkout Home Assistant Core (dev)
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: home-assistant/core
ref: dev
path: lib/home-assistant

- name: Set up uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true

- name: Install Home Assistant
# The sync tool imports only `homeassistant` and reads ZHA's files as
# text (it never imports ZHA), so ZHA itself is not installed — avoiding a
# joint resolution of ZHA's and HA-dev's pins. HA requires Python 3.14.2+.
run: |
uv venv --python '>=3.14.2'
uv pip install -e ./lib/home-assistant

- name: Sync constants
# No separate format step: the tool emits ruff-clean output, and the pull
# request's own pre-commit CI runs the repo-pinned ruff as the check.
# Capture the tool's summary of what changed for the PR body.
run: |
set -o pipefail # the default step shell lacks it, so `| tee` would hide a tool failure
.venv/bin/python -m tools.sync_constants | tee "$RUNNER_TEMP/sync.txt"
{
echo 'Automated copy of the Home Assistant enums ZHA mirrors, generated by'
echo '`python -m tools.sync_constants` against the Home Assistant `dev` branch.'
echo 'Please review before merging.'
echo
echo '<details><summary>Sync output</summary>'
echo
echo '```'
cat "$RUNNER_TEMP/sync.txt"
echo '```'
echo
echo '</details>'
} > "$RUNNER_TEMP/pr-body.md"

- name: Create pull request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ steps.app-token.outputs.token }}
add-paths: zha/
commit-message: "Sync device classes from Home Assistant"
committer: "${{ steps.app-token.outputs.app-slug }}[bot] <${{ steps.app-user.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com>"
author: "${{ steps.app-token.outputs.app-slug }}[bot] <${{ steps.app-user.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com>"
branch: sync/device-classes
delete-branch: true
title: "Sync device classes from Home Assistant"
body-path: ${{ runner.temp }}/pr-body.md
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ testing = [
"pytest",
"coloredlogs",
"python-slugify",
# Mainly used for device class synchronization, HA requires Python 3.14.2
"homeassistant>=2026.7.0; python_full_version >= '3.14.2'",
]

[dependency-groups]
Expand Down
12 changes: 12 additions & 0 deletions tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,15 @@ If entities change, the current diagnostics JSON will no longer be valid and CI
```console
$ python -m tools.regenerate_diagnostics
```

## Sync constants from Home Assistant

ZHA keeps near 1:1 copies of some Home Assistant enums (unit enums in `zha.units`, and the device-class / mode enums under `zha.application.platforms`). This tool copies them verbatim — including docstrings and comments — from the installed `homeassistant` package, so they stay in sync. Unit enums are added, refreshed, or removed to match HA; the device-class / mode enums are a fixed set that is refreshed in place (a brand-new one in HA has to be added to the tool by hand). Run it from the repo root; it needs `homeassistant` installed but reads ZHA's files as text (it never imports them, so `zha`/`zha-quirks` don't need to be installed).

```console
$ python -m tools.sync_constants # copy the enums from HA into ZHA
$ python -m tools.sync_constants --check # dry run, exits 1 if anything is out of sync
$ ruff format zha/ # normalise whitespace afterwards
```

Only enums are synced. ZHA-only symbols and the hand-maintained backwards-compatibility constants at the end of `zha.units` are left untouched. The `Sync device classes from Home Assistant` GitHub workflow runs this against Home Assistant's `dev` branch on a schedule and opens a pull request with the result.
194 changes: 0 additions & 194 deletions tools/compare_constants.py

This file was deleted.

Loading
Loading