Skip to content

Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks#794

Merged
raman325 merged 17 commits into
mainfrom
feat/improved-autolabeler
Jan 15, 2026
Merged

Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks#794
raman325 merged 17 commits into
mainfrom
feat/improved-autolabeler

Conversation

@raman325

@raman325 raman325 commented Jan 15, 2026

Copy link
Copy Markdown
Owner

Proposed change

Comprehensive CI/CD improvements covering labeling, auto-merge, workflow organization, and Python testing.

Labeling Improvements

Replace release-drafter's autolabeler with dedicated GitHub Actions that support both adding AND removing labels when patterns match or no longer match:

  • actions/labeler (with sync-labels: true) for file-based labels
  • github/issue-labeler (with sync-labels: 1) for body-based (checkbox) labels

Auto-merge Improvements

Replace branch protection-based auto-merge with explicit check polling:

  • Auto-merge workflow polls for specific checks directly via GitHub API
  • Two categories: MUST_PASS (always run) and IF_RUN_PASS (conditional)
  • Pattern matching support (e.g., Python / Pytest * matches all Pytest versions)
  • HACS and Hassfest provide natural delay as required checks (~30s each)
  • No branch protection ruleset needed

Workflow Organization

Consolidate and reorganize CI workflows:

  • Combined frontend.yaml and integration.yaml into single integration.yaml
  • Reusable workflows for Python and Frontend checks (better UI hierarchy)
  • HACS and Hassfest run unconditionally (quick validation checks)
  • Path filtering via dorny/paths-filter for Python and Frontend jobs
  • Skipped jobs show explicitly in UI for transparency

Python Check Improvements

  • Ruff: Added format check and linting
  • Pytest matrix: Run tests on multiple Python versions
  • Version variables: TARGET_PYTHON and OTHER_PYTHON_VERSIONS env vars
    • Centralized version management in python-checks.yml
    • Auto-merge uses pattern matching, no hardcoded versions
  • Coverage: Only uploaded for target Python version

File Changes

Added:

  • .github/labeler.yml - file-based label patterns
  • .github/issue-labeler.yml - body-based (checkbox) patterns
  • .github/workflows/labeler.yaml - runs both labelers on PR events
  • .github/workflows/python-checks.yml - reusable Ruff + Pytest workflow
  • .github/workflows/frontend-checks.yml - reusable Vitest/Lint workflow

Updated:

  • .github/workflows/integration.yaml - orchestrates all checks
  • .github/workflows/repository.yaml - auto-merge with pattern-based check polling
  • TODO.md - added item for mypy/type checking (deferred)

Removed:

  • .github/workflows/frontend.yaml (consolidated)
  • Autolabeler section from release-drafter.yml

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: N/A
  • This PR is related to issue: N/A

Use actions/labeler for file-based labels and github/issue-labeler for
body-based labels. Both support sync-labels to add AND remove labels
when patterns match or no longer match.

- Added .github/labeler.yml for file-based label patterns
- Added .github/issue-labeler.yml for body-based (checkbox) patterns
- Added .github/workflows/labeler.yaml to run both labelers
- Removed autolabeler section from release-drafter.yml
- Removed related TODO item

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 15, 2026 06:12
@github-actions github-actions Bot added documentation Documentation changes enhancement New feature or request github_actions labels Jan 15, 2026
@github-actions github-actions Bot added the code-quality Pull requests that improve code quality label Jan 15, 2026

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

This PR replaces release-drafter's autolabeler with dedicated GitHub Actions for labeling pull requests. The change addresses a limitation where release-drafter only adds labels but never removes them when patterns no longer match (e.g., when a checkbox is unchecked).

Changes:

  • Added dedicated labeling workflow using actions/labeler (file-based) and github/issue-labeler (body-based) with sync-labels enabled
  • Migrated autolabeler configuration from release-drafter.yml to separate configuration files
  • Removed completed TODO item about exploring alternative autolabeler workflows

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
.github/workflows/labeler.yaml New workflow with two jobs for file-based and body-based labeling
.github/labeler.yml File-based label patterns migrated from release-drafter autolabeler
.github/issue-labeler.yml Body-based (checkbox) label patterns migrated from release-drafter autolabeler
.github/release-drafter.yml Removed autolabeler section, retained release notes generation functionality
TODO.md Removed completed TODO item about autolabeler alternatives

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/issue-labeler.yml Outdated
Comment thread .github/issue-labeler.yml Outdated
Comment thread .github/labeler.yml
Self-contained workflow that polls for all other checks to complete.
Use "All Checks Pass" as the single required status check in branch
protection - solves the issue where path-filtered workflows don't
always run.

No external action dependencies - uses inline gh API calls.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@raman325 raman325 removed the code-quality Pull requests that improve code quality label Jan 15, 2026
raman325 and others added 3 commits January 15, 2026 01:33
Fixes race condition where CI gate could complete before slower
workflows even start.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Workflows now always trigger but skip jobs internally when paths don't
match. This ensures a consistent number of check runs regardless of
which files changed.

Uses dorny/paths-filter to check changed files, then jobs use if:
conditions to skip when no relevant changes.

Also removed initial delay from CI gate since workflows now start
immediately.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove 'dependencies' from body-based labeler to avoid conflict with
  file-based labeler (both had sync-labels which could fight)
- Match both [x] and [X] in checkbox patterns for manual edits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jan 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.26%. Comparing base (4db35c4) to head (db187bd).
⚠️ Report is 9 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #794   +/-   ##
=======================================
  Coverage   95.26%   95.26%           
=======================================
  Files          29       29           
  Lines        2384     2384           
  Branches       88       88           
=======================================
  Hits         2271     2271           
  Misses        113      113           
Flag Coverage Δ
python 95.12% <ø> (ø)
typescript 96.53% <ø> (ø)

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 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.

raman325 and others added 3 commits January 15, 2026 01:42
After all checks appear complete, wait 60 seconds and re-verify to
catch late-arriving checks like Codecov that report asynchronously.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of using branch protection required checks + CI gate workflow:
- Auto-merge now polls for specific checks directly
- "Check Changes" must exist and pass (always runs)
- Other checks (Pytest, HACS, etc.) must pass IF they run
- Deleted CI gate workflow and branch protection ruleset

This simplifies the CI setup and avoids race conditions with
late-arriving checks like Codecov.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Give workflows 15 seconds to register their check runs before
polling starts. This prevents the edge case where auto-merge
starts polling before other workflows have registered, which
would cause a "No required checks found" error.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@raman325 raman325 force-pushed the feat/improved-autolabeler branch from 94c4000 to 52c6d19 Compare January 15, 2026 06:56
raman325 and others added 5 commits January 15, 2026 01:59
Merge frontend.yaml into integration.yaml with a single check-changes
job that outputs both python and frontend filters. Jobs conditionally
run based on their respective filter outputs.

Benefits:
- Single paths-filter execution instead of two
- Unified workflow view in GitHub Actions
- Simpler auto-merge check list (one Check Changes job)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split integration.yaml into reusable workflows:
- python-checks.yml: Pytest, HACS, Hassfest jobs
- frontend-checks.yml: Yarn Lint and Build, Vitest jobs
- integration.yaml: Orchestrates with check-changes and calls reusable workflows

Benefits:
- GitHub UI shows collapsible "Python" and "Frontend" groups
- Clear visual hierarchy in the Actions tab
- Maintains skip behavior via caller job conditions

Update auto-merge to use prefixed check names (e.g., "Python / Pytest")
since reusable workflow jobs get prefixed with caller job name.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
HACS and Hassfest validate the Home Assistant integration as a whole,
not just Python code. "Integration" better reflects the scope of these
checks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
HACS and Hassfest validate different aspects of the integration:
- HACS: hacs.json, README.md, custom_components/ structure
- Hassfest: custom_components/ manifest, translations, services

Each now has its own path filter and runs as a direct job rather than
nested under Python. This means they only run when relevant files change.

Structure:
- Check Changes: Outputs python, hacs, hassfest, frontend filters
- Python (reusable): Pytest only
- HACS (direct): Runs when hacs.json, README.md, or custom_components changes
- Hassfest (direct): Runs when custom_components changes
- Frontend (reusable): Vitest, Yarn Lint and Build

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove path filtering for HACS and Hassfest - they're quick validation
checks (~30 seconds) that can run on every PR. Making them required for
auto-merge provides a natural delay, eliminating the need for an
artificial sleep.

Changes:
- HACS and Hassfest run unconditionally (no needs/if)
- Moved to MUST_PASS in auto-merge (always exist and must pass)
- Removed 60-second sleep delay (HACS/Hassfest provide natural delay)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@raman325 raman325 changed the title Replace release-drafter autolabeler with dedicated labeling actions Improve CI/CD: labeling, auto-merge, and workflow organization Jan 15, 2026
@github-actions github-actions Bot added the code-quality Pull requests that improve code quality label Jan 15, 2026
@raman325 raman325 removed enhancement New feature or request code-quality Pull requests that improve code quality labels Jan 15, 2026
Python checks now include:
- Ruff: Format check and linting (runs on 3.13)
- Mypy: Type checking (runs on 3.13)
- Pytest: Tests with coverage (matrix: 3.13, 3.14)

Notes:
- Static analysis (Ruff, Mypy) runs on single version
- Pytest uses matrix with fail-fast: false for independent results
- Coverage only uploaded for 3.13 to avoid duplicates
- Python 3.14 uses allow-prereleases: true

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions github-actions Bot added code-quality Pull requests that improve code quality enhancement New feature or request labels Jan 15, 2026
Mypy has ~30 errors in the codebase. Removing from this PR to keep
scope focused on CI improvements.

Added TODO to:
- Add mypy (or alternative) to pre-commit hooks
- Add type checking CI job
- Explore alternatives (Astral may have a replacement)
- Fix existing type errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@raman325 raman325 changed the title Improve CI/CD: labeling, auto-merge, and workflow organization Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks Jan 15, 2026
raman325 and others added 2 commits January 15, 2026 02:34
Define Python versions as env vars at workflow level:
- TARGET_PYTHON: Primary version for coverage and static analysis
- OTHER_PYTHON_VERSIONS: JSON array of additional test versions

A setup job computes the combined matrix and passes it to downstream
jobs. This makes version management centralized - just update the env
vars to test different Python versions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use * suffix for pattern matching in IF_RUN_PASS checks:
- "Python / Pytest *" matches "Python / Pytest (3.13)", "Python / Pytest (3.14)", etc.

This decouples repository.yaml from specific Python versions defined in
python-checks.yml. When Python versions change, only python-checks.yml
needs updating.

Also optimized to fetch all check runs once per iteration instead of
per-check queries.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@raman325 raman325 merged commit 27c0ce3 into main Jan 15, 2026
22 checks passed
@raman325 raman325 deleted the feat/improved-autolabeler branch January 15, 2026 07:38
raman325 added a commit that referenced this pull request Jan 15, 2026
* main:
  Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)
  Run autolabeling on PR description edits (#793)
raman325 added a commit that referenced this pull request Jan 15, 2026
* main:
  Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)
  Run autolabeling on PR description edits (#793)
raman325 added a commit that referenced this pull request Jan 15, 2026
…n checks (#794)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
raman325 added a commit that referenced this pull request Jan 15, 2026
* main:
  Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)
  Run autolabeling on PR description edits (#793)
raman325 added a commit that referenced this pull request Jan 15, 2026
* main:
  Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)
  Run autolabeling on PR description edits (#793)
raman325 added a commit that referenced this pull request Jan 15, 2026
* main:
  Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)
  Run autolabeling on PR description edits (#793)
raman325 added a commit that referenced this pull request Jan 15, 2026
* main:
  Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)
  Run autolabeling on PR description edits (#793)
raman325 added a commit that referenced this pull request Jan 15, 2026
* main:
  Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)
  Run autolabeling on PR description edits (#793)
raman325 added a commit that referenced this pull request Jan 15, 2026
…n checks (#794)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
@raman325 raman325 added the github-config Changes to .github/ configuration files label Jan 15, 2026
raman325 added a commit that referenced this pull request Jan 15, 2026
…n checks (#794)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
raman325 added a commit that referenced this pull request Jan 15, 2026
…n checks (#794)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
raman325 added a commit that referenced this pull request Jan 20, 2026
…n checks (#794)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
raman325 added a commit that referenced this pull request Apr 21, 2026
* Add Zigbee2MQTT lock provider for MQTT-based locks

Add support for Zigbee2MQTT locks by publishing/subscribing to MQTT topics.
This enables user code management for locks exposed via Zigbee2MQTT:
- Detects Zigbee2MQTT devices by their device identifiers (zigbee2mqtt_*)
- Uses MQTT publish to set/clear PIN codes
- Subscribes to device topic for push updates
- Polls via MQTT get requests with async response handling

Maps to the "mqtt" domain in INTEGRATIONS_CLASS_MAP since Zigbee2MQTT
devices appear as MQTT entities in Home Assistant.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add mqtt to after_dependencies in manifest

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Run autolabeling on PR description edits (#793)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Improve CI/CD: labeling, auto-merge, workflow organization, and Python checks (#794)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Update Zigbee2MQTT provider for current BaseLock interface

Align zigbee2mqtt.py with codebase changes since the PR was created:
- Use SlotCode.EMPTY instead of "" for cleared/empty slots
- Rename subscribe/unsubscribe_push_updates to setup/teardown_push_subscription
- Rename async_is_connection_up to async_is_integration_connected
- Fix async_set_usercode signature: usercode is str, not int | str
- Fix return types to dict[int, str | SlotCode]
- Import SlotCode from models, use LOGGER from providers.const
- Remove redundant lock_config_entry field (already in BaseLock)
- Use comprehension for Zigbee2MQTT device identifier check

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(hacs): allow branch installs by disabling zip_release

Made-with: Cursor

* fix(config_flow): match MQTT locks using HA platform mqtt for Z2M

Document Zigbee2MQTT prerequisites in README.

Made-with: Cursor

* fix(config_flow): build lock entity filters from INTEGRATIONS_CLASS_MAP

Avoid pkgutil.iter_modules(providers) returning empty under HACS/HA, which
made the selector show no locks.

Made-with: Cursor

* fix(mqtt): stop using removed hass.components for MQTT API

Use homeassistant.components.mqtt async_publish/async_subscribe and
mqtt_config_entry_enabled per current Home Assistant core.

Made-with: Cursor

* fix(mqtt): dispatch Z2M MQTT callbacks via hass.add_job for thread safety

Made-with: Cursor

* fix(mqtt): clear Z2M PIN with pin_code null and user_type

Made-with: Cursor

* fix(mqtt): deliver Z2M MQTT payloads with loop.call_soon_threadsafe

Made-with: Cursor

* fix(mqtt): optimistic coordinator updates after Z2M set/clear publish

Made-with: Cursor

* fix(zigbee2mqtt): avoid false EMPTY when PIN is hidden in MQTT state

Zigbee2MQTT omits pin_code when expose_pin is false; treating that as an empty slot prevented sync from calling clear_usercode when disabling.

Also refresh coordinator on pin_code_deleted actions.

Adds unit tests for users payload parsing.

Made-with: Cursor

* style(zigbee2mqtt): satisfy ruff D202 after docstring

Made-with: Cursor

* chore: add git commit template and setup helpers

Made-with: Cursor:

* Revert "chore: add git commit template and setup helpers"

This reverts commit 07302ef.

* docs(README): include Zigbee2MQTT in supported install step

Made-with: Cursor

* fix(zigbee2mqtt): use get_managed_slots for EntryConfig (main API)

get_entry_data was removed upstream; async_get_usercodes must resolve
managed slots via the same helper as the rest of the integration.

Made-with: Cursor

* test(zigbee2mqtt): minimal mock includes lock.platform for BaseLock

BaseLock.__post_init__ logs platform and entry ids when device_id is missing.

Made-with: Cursor

* docs(config_flow): explain lock picker uses INTEGRATIONS_CLASS_MAP vs pkgutil

Made-with: Cursor

* chore: gitignore .cursor (local Cursor IDE rules)

Made-with: Cursor

* fix(zigbee2mqtt): accept source in async_set_usercode (BaseLock API)

Required by async_internal_set_usercode after main merge; prevents
TypeError when sync manager sets usercodes.

Made-with: Cursor

* chore::Clean up comments in config_flow.py

Removed comments explaining the lock entity picker and integration handling.

* refactor(zigbee2mqtt): remove unused USER_STATUS constants

Made-with: Cursor

* test(zigbee2mqtt): cover setup_push_subscription and push_update path

- Assert async_subscribe uses zigbee2mqtt/{friendly_name} topic
- Verify MQTT callback schedules coordinator.push_update on the loop
- Add idempotent setup and LockDisconnected when device is not Z2M

Made-with: Cursor

* test(zigbee2mqtt): cover async_get_usercodes MQTT futures and timeouts

- Assert one get publish per managed slot on the device get topic
- Resolve pin_code responses into slot values
- Timeout path maps to SlotCode.EMPTY

Made-with: Cursor

* docs: wrap Zigbee2MQTT footnote for markdownlint (MD013)

Made-with: Cursor

* fix(zigbee2mqtt): refresh Z2M topic name, loop futures, parallel get

- Read device name each call so HA renames update MQTT topics
- Use running loop create_future for pin_code waits (Copilot review)
- Publish all get requests then gather wait_for per slot concurrently

Made-with: Cursor

* fix(zigbee2mqtt): subscribe in async_setup, split availability, stricter PIN reads and tests

Made-with: Cursor

* docs(zigbee2mqtt): clarify code events and optimistic push_update

Made-with: Cursor

* fix(zigbee2mqtt): explicit PIN checks, clearer non-Z2M disconnect, tests

Made-with: Cursor

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* docs(readme): wrap Zigbee2MQTT footnote for markdownlint MD013

Made-with: Cursor

* fix(zigbee2mqtt): use hass.add_job for MQTT callbacks (HA deprecates async_add_job)

Made-with: Cursor

* fix(zigbee2mqtt): serial GET usercodes and tolerate per-slot timeouts

Parallel gather raised LockDisconnected on any slot timeout, failing the
whole refresh and leaving coordinator.data without keys — SlotSyncManager
then skipped those slots. Restore sequential get with per-slot EMPTY on
timeout/error so every managed slot has coordinator state.

Made-with: Cursor

* refactor(zigbee2mqtt): align try/except/else with review feedback

Made-with: Cursor

* docs(zigbee2mqtt): shorten setup_push_subscription docstring

Made-with: Cursor

* fix(zigbee2mqtt): wrap setup_push_subscription docstring for flake8 E501

Made-with: Cursor

* fix(zigbee2mqtt): use UNREADABLE_CODE on GET read failures

Transient publish/timeout/wait errors map to SlotCode.UNREADABLE_CODE so sync
does not assume confirmed-empty slots during MQTT outages. Log at warning.

Docstring for _subscribe_or_log kept to two lines (closing quote on own line).

Made-with: Cursor

* fix(zigbee2mqtt): log GET failures at debug level

Transient MQTT publish/timeout/read errors are expected during churn;
keep UNREADABLE_CODE behavior but avoid warning spam in HA logs.

Made-with: Cursor

* test(zigbee2mqtt): raise zigbee2mqtt coverage above 96%

Cover bool PIN payload guard and async_clear_usercode OSError path (publish
failure uses HomeAssistantError/OSError; RuntimeError skipped that branch).

Made-with: Cursor

---------

Co-authored-by: raman325 <7243222+raman325@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code-quality Pull requests that improve code quality documentation Documentation changes enhancement New feature or request github-config Changes to .github/ configuration files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants