Compare commits

..

2 Commits

Author SHA1 Message Date
Erik b90440443f Add did not trigger trace when behavior first and all are not met 2026-06-30 20:57:41 +02:00
Stefan Agner 5a2329df97 Remove unused Silicon Labs Flasher add-on manager (#175210)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:56:34 +02:00
7 changed files with 357 additions and 283 deletions
@@ -1,125 +0,0 @@
name: Set up Python and restore or build the venv
description: >-
Sets up uv and the managed interpreter, then restores the full venv from the
cache. On a miss it rebuilds the venv from requirements instead of
hard-failing, so jobs survive a transient miss when the entry is evicted under
the repo cache size limit. Only the prepare job sets save to true and writes
the cache, so the validating jobs add no extra cache pressure.
inputs:
python-version:
description: The Python version uv should install and use.
required: true
uv-version:
description: The uv version setup-uv should install.
required: true
python-cache-key:
description: The shared python_cache_key from the info job.
required: true
uv-cache-dir:
description: The uv cache directory (env.UV_CACHE_DIR from the caller).
required: true
apt-cache-version:
description: The apt cache version (env.APT_CACHE_VERSION from the caller).
required: true
save:
description: Whether to save the rebuilt venv and uv cache. Only the prepare job should.
default: "false"
outputs:
python-version:
description: The Python version uv reports as installed.
value: ${{ steps.python.outputs.python-version }}
runs:
using: composite
steps:
- name: Set up uv and managed Python
id: python
uses: ./.github/actions/setup-uv-python
with:
uv-version: ${{ inputs.uv-version }}
python-version: ${{ inputs.python-version }}
- name: Restore full Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
inputs.python-cache-key }}
- name: Generate partial uv restore key
if: steps.cache-venv.outputs.cache-hit != 'true'
id: generate-uv-key
shell: bash
env:
RUNNER_OS: ${{ runner.os }}
RUNNER_ARCH: ${{ runner.arch }}
PYTHON_VERSION: ${{ steps.python.outputs.python-version }}
HASH_FILES: ${{ hashFiles('requirements.txt', 'requirements_all.txt', 'requirements_test.txt', 'homeassistant/package_constraints.txt') }}
run: |
partial_key="${RUNNER_OS}-${RUNNER_ARCH}-${PYTHON_VERSION}-uv-"
echo "partial_key=${partial_key}" >> $GITHUB_OUTPUT
echo "full_key=${partial_key}${HASH_FILES}" >> $GITHUB_OUTPUT
- name: Restore uv wheel cache
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ inputs.uv-cache-dir }}
key: ${{ steps.generate-uv-key.outputs.full_key }}
restore-keys: ${{ steps.generate-uv-key.outputs.partial_key }}
# Only runs on a cache miss when the venv is rebuilt. Composite steps cannot
# set timeout-minutes, so a stuck apt download is bounded by the job-level
# timeout instead of a per-step cap.
- name: Install additional OS dependencies
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: ./.github/actions/cache-apt-packages
with:
packages: >-
bluez
ffmpeg
libturbojpeg
libxml2-utils
libavcodec-dev
libavdevice-dev
libavfilter-dev
libavformat-dev
libavutil-dev
libswresample-dev
libswscale-dev
libudev-dev
version: ${{ inputs.apt-cache-version }}
execute_install_scripts: true
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
id: create-venv
shell: bash
env:
PYTHON_VERSION: ${{ steps.python.outputs.python-version }}
run: |
uv venv venv --python "${PYTHON_VERSION}"
. venv/bin/activate
python --version
uv pip install -r requirements.txt
uv pip install -r requirements_all.txt -r requirements_test.txt
uv pip install -e . --config-settings editable_mode=compat
- name: Prune uv cache
if: inputs.save == 'true' && steps.cache-venv.outputs.cache-hit != 'true'
shell: bash
run: |
. venv/bin/activate
uv cache prune --ci
- name: Save uv wheel cache
if: inputs.save == 'true' && steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ inputs.uv-cache-dir }}
key: ${{ steps.generate-uv-key.outputs.full_key }}
- name: Save full Python virtual environment
if: always() && inputs.save == 'true' && steps.create-venv.outcome == 'success'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
inputs.python-cache-key }}
@@ -1,46 +0,0 @@
name: Set up uv and managed Python
description: >-
Pins uv (avoids the raw.githubusercontent.com manifest fetch on cache miss)
and proactively installs the requested Python so cached venvs created with
`uv venv` resolve their interpreter symlinks in jobs that only restore the
venv. setup-uv alone only sets UV_PYTHON, it does not actually fetch the
interpreter until uv first uses it, so jobs that just activate the venv
blow up with broken symlinks on cache hit.
inputs:
python-version:
description: The Python version uv should install and use.
required: true
uv-version:
description: The uv version setup-uv should install.
required: true
outputs:
python-version:
description: The Python version uv reports as installed.
value: ${{ steps.uv.outputs.python-version }}
runs:
using: composite
steps:
- name: Set up uv
id: uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
version: ${{ inputs.uv-version }}
python-version: ${{ inputs.python-version }}
# Persist astral's managed Python across jobs so 'uv venv' below is
# fast on the second job onwards.
cache-python: true
# Lint-only and codegen jobs touch no Python deps, so the post-step
# cache save would otherwise abort the job.
ignore-nothing-to-cache: true
# setup-uv only sets UV_PYTHON; it does not fetch the interpreter until uv
# first uses it. Jobs that only restore and activate a cached venv never
# trigger that lazy install, so without this step they hit broken
# interpreter symlinks on a cache hit.
- name: Install Python interpreter
shell: bash
env:
PYTHON_VERSION: ${{ inputs.python-version }}
run: uv python install "${PYTHON_VERSION}"
+235 -92
View File
@@ -37,7 +37,7 @@ on:
type: boolean
env:
CACHE_VERSION: 4
CACHE_VERSION: 3
MYPY_CACHE_VERSION: 1
HA_SHORT_VERSION: "2026.8"
ADDITIONAL_PYTHON_VERSIONS: "[]"
@@ -89,8 +89,6 @@ jobs:
mariadb_groups: ${{ steps.info.outputs.mariadb_groups }}
postgresql_groups: ${{ steps.info.outputs.postgresql_groups }}
python_versions: ${{ steps.info.outputs.python_versions }}
default_python: ${{ steps.info.outputs.default_python }}
uv_version: ${{ steps.info.outputs.uv_version }}
test_full_suite: ${{ steps.info.outputs.test_full_suite }}
test_group_count: ${{ steps.info.outputs.test_group_count }}
test_groups: ${{ steps.info.outputs.test_groups }}
@@ -237,11 +235,6 @@ jobs:
echo "postgresql_groups=${postgresql_groups}" >> $GITHUB_OUTPUT
echo "python_versions: ${all_python_versions}"
echo "python_versions=${all_python_versions}" >> $GITHUB_OUTPUT
echo "default_python: ${default_python}"
echo "default_python=${default_python}" >> $GITHUB_OUTPUT
uv_version=$(grep '^uv==' requirements.txt | cut -d'=' -f3)
echo "uv_version: ${uv_version}"
echo "uv_version=${uv_version}" >> $GITHUB_OUTPUT
echo "test_full_suite: ${test_full_suite}"
echo "test_full_suite=${test_full_suite}" >> $GITHUB_OUTPUT
echo "integrations_glob: ${integrations_glob}"
@@ -351,18 +344,82 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }} and build venv
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ matrix.python-version }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
save: "true"
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Generate partial uv restore key
if: steps.cache-venv.outputs.cache-hit != 'true'
id: generate-uv-key
env:
RUNNER_OS: ${{ runner.os }}
RUNNER_ARCH: ${{ runner.arch }}
PYTHON_VERSION: ${{ steps.python.outputs.python-version }}
HASH_FILES: ${{ hashFiles('requirements.txt', 'requirements_all.txt', 'requirements_test.txt', 'homeassistant/package_constraints.txt') }}
run: |
partial_key="${RUNNER_OS}-${RUNNER_ARCH}-${PYTHON_VERSION}-uv-"
echo "partial_key=${partial_key}" >> $GITHUB_OUTPUT
echo "full_key=${partial_key}${HASH_FILES}" >> $GITHUB_OUTPUT
- name: Restore uv wheel cache
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ env.UV_CACHE_DIR }}
key: ${{ steps.generate-uv-key.outputs.full_key }}
restore-keys: ${{ steps.generate-uv-key.outputs.partial_key }}
- name: Install additional OS dependencies
if: steps.cache-venv.outputs.cache-hit != 'true'
timeout-minutes: 10
uses: ./.github/actions/cache-apt-packages
with:
packages: >-
bluez
ffmpeg
libturbojpeg
libxml2-utils
libavcodec-dev
libavdevice-dev
libavfilter-dev
libavformat-dev
libavutil-dev
libswresample-dev
libswscale-dev
libudev-dev
version: ${{ env.APT_CACHE_VERSION }}
execute_install_scripts: true
- name: Read uv version from requirements.txt
if: steps.cache-venv.outputs.cache-hit != 'true'
id: read-uv-version
run: |
echo "version=$(grep '^uv==' requirements.txt | cut -d'=' -f3)" >> "$GITHUB_OUTPUT"
- name: Set up uv
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
version: ${{ steps.read-uv-version.outputs.version }}
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
id: create-venv
run: |
python -m venv venv
. venv/bin/activate
python --version
uv pip install -r requirements.txt
uv pip install -r requirements_all.txt -r requirements_test.txt
uv pip install -e . --config-settings editable_mode=compat
- name: Dump pip freeze
run: |
python -m venv venv
. venv/bin/activate
python --version
uv pip freeze >> pip_freeze.txt
@@ -377,6 +434,26 @@ jobs:
- name: Check dirty
run: |
./script/check_dirty
- name: Prune uv cache
if: steps.cache-venv.outputs.cache-hit != 'true'
id: prune-uv-cache
run: |
. venv/bin/activate
uv cache prune --ci
- name: Save uv wheel cache
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ env.UV_CACHE_DIR }}
key: ${{ steps.generate-uv-key.outputs.full_key }}
- name: Save base Python virtual environment
if: always() && steps.create-venv.outcome == 'success'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
hassfest:
name: Check hassfest
@@ -401,15 +478,21 @@ jobs:
with:
packages: libturbojpeg
version: ${{ env.APT_CACHE_VERSION }}
- name: Set up Python and restore venv
- name: Set up Python
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ needs.info.outputs.default_python }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
python-version-file: ".python-version"
check-latest: true
- name: Restore full Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Run hassfest
run: |
. venv/bin/activate
@@ -432,15 +515,21 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python and restore venv
- name: Set up Python
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ needs.info.outputs.default_python }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
python-version-file: ".python-version"
check-latest: true
- name: Restore full Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Run gen_requirements_all.py
run: |
. venv/bin/activate
@@ -464,13 +553,13 @@ jobs:
persist-credentials: false
- name: Set up Python
id: python
uses: ./.github/actions/setup-uv-python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ needs.info.outputs.default_python }}
python-version-file: ".python-version"
check-latest: true
- name: Run gen_copilot_instructions.py
run: |
uv run --no-project python -m script.gen_copilot_instructions validate
python -m script.gen_copilot_instructions validate
dependency-review:
name: Dependency review
@@ -517,15 +606,21 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }} and restore venv
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ matrix.python-version }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Extract license data
env:
PYTHON_VERSION: ${{ matrix.python-version }}
@@ -562,15 +657,21 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python and restore venv
- name: Set up Python
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ needs.info.outputs.default_python }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
python-version-file: ".python-version"
check-latest: true
- name: Restore full Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Register pylint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pylint.json"
@@ -609,15 +710,21 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python and restore venv
- name: Set up Python
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ needs.info.outputs.default_python }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
python-version-file: ".python-version"
check-latest: true
- name: Restore full Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Register pylint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pylint.json"
@@ -654,21 +761,27 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
id: python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version-file: ".python-version"
check-latest: true
- name: Generate partial mypy restore key
id: generate-mypy-key
run: |
mypy_version=$(cat requirements_test.txt | grep 'mypy.*=' | cut -d '=' -f 3)
echo "version=${mypy_version}" >> $GITHUB_OUTPUT
echo "key=mypy-${MYPY_CACHE_VERSION}-${mypy_version}-${HA_SHORT_VERSION}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT
- name: Set up Python and restore venv
id: python
uses: ./.github/actions/restore-or-build-venv
- name: Restore full Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ needs.info.outputs.default_python }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Restore mypy cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
@@ -725,15 +838,21 @@ jobs:
libturbojpeg
version: ${{ env.APT_CACHE_VERSION }}
execute_install_scripts: true
- name: Set up Python and restore venv
- name: Set up Python
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ needs.info.outputs.default_python }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
python-version-file: ".python-version"
check-latest: true
- name: Restore full Python virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Run split_tests.py
env:
TEST_GROUP_COUNT: ${{ needs.info.outputs.test_group_count }}
@@ -784,15 +903,21 @@ jobs:
libxml2-utils
version: ${{ env.APT_CACHE_VERSION }}
execute_install_scripts: true
- name: Set up Python ${{ matrix.python-version }} and restore venv
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ matrix.python-version }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
@@ -920,15 +1045,21 @@ jobs:
libxml2-utils
version: ${{ env.APT_CACHE_VERSION }}
execute_install_scripts: true
- name: Set up Python ${{ matrix.python-version }} and restore venv
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ matrix.python-version }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
@@ -1070,15 +1201,21 @@ jobs:
with:
packages: postgresql-server-dev-14
version: ${{ env.APT_CACHE_VERSION }}
- name: Set up Python ${{ matrix.python-version }} and restore venv
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ matrix.python-version }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
@@ -1232,15 +1369,21 @@ jobs:
libxml2-utils
version: ${{ env.APT_CACHE_VERSION }}
execute_install_scripts: true
- name: Set up Python ${{ matrix.python-version }} and restore venv
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: ./.github/actions/restore-or-build-venv
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
uv-version: ${{ needs.info.outputs.uv_version }}
python-version: ${{ matrix.python-version }}
python-cache-key: ${{ needs.info.outputs.python_cache_key }}
uv-cache-dir: ${{ env.UV_CACHE_DIR }}
apt-cache-version: ${{ env.APT_CACHE_VERSION }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
@@ -28,12 +28,7 @@ OTBR_ADDON_NAME = "OpenThread Border Router"
OTBR_ADDON_MANAGER_DATA = "openthread_border_router"
OTBR_ADDON_SLUG = "core_openthread_border_router"
ZIGBEE_FLASHER_ADDON_NAME = "Silicon Labs Flasher"
ZIGBEE_FLASHER_ADDON_MANAGER_DATA = "silabs_flasher"
ZIGBEE_FLASHER_ADDON_SLUG = "core_silabs_flasher"
SILABS_MULTIPROTOCOL_ADDON_SLUG = "core_silabs_multiprotocol"
SILABS_FLASHER_ADDON_SLUG = "core_silabs_flasher"
Z2M_EMBER_DOCS_URL = "https://www.zigbee2mqtt.io/guide/adapters/emberznet.html"
@@ -36,9 +36,6 @@ from .const import (
OTBR_ADDON_SLUG,
Z2M_ADDON_NAME,
Z2M_ADDON_SLUG_REGEX,
ZIGBEE_FLASHER_ADDON_MANAGER_DATA,
ZIGBEE_FLASHER_ADDON_NAME,
ZIGBEE_FLASHER_ADDON_SLUG,
)
from .helpers import async_firmware_update_context
@@ -128,18 +125,6 @@ def get_otbr_addon_manager(hass: HomeAssistant) -> WaitingAddonManager:
)
@singleton(ZIGBEE_FLASHER_ADDON_MANAGER_DATA)
@callback
def get_zigbee_flasher_addon_manager(hass: HomeAssistant) -> WaitingAddonManager:
"""Get the flasher add-on manager."""
return WaitingAddonManager(
hass,
_LOGGER,
ZIGBEE_FLASHER_ADDON_NAME,
ZIGBEE_FLASHER_ADDON_SLUG,
)
@callback
def get_z2m_addon_manager(hass: HomeAssistant, slug: str) -> WaitingAddonManager:
"""Get the Z2M add-on manager."""
+6
View File
@@ -641,6 +641,9 @@ class EntityTriggerBase(Trigger):
target_state_change_data.targeted_entity_states,
)
if matches != included:
report_not_triggered(
"not_all_targets_matched", matches=matches, included=included
)
return
elif behavior == BEHAVIOR_FIRST:
# Note: It's enough to test for exactly 1 match here because if there
@@ -651,6 +654,9 @@ class EntityTriggerBase(Trigger):
target_state_change_data.targeted_entity_states,
)
if matches != 1:
report_not_triggered(
"behavior_first_not_satisfied", matches=matches
)
return
@callback
+116
View File
@@ -4277,6 +4277,122 @@ async def _arm_off_to_on_trigger(
)
async def _arm_off_to_on_trigger_with_diagnostics(
hass: HomeAssistant,
entity_ids: list[str],
behavior: str,
calls: list[dict[str, Any]],
did_not_trigger_reports: list[NotTriggeredInfo],
) -> CALLBACK_TYPE:
"""Set up _OffToOnTrigger with both an action and a did_not_trigger reporter."""
async def async_get_triggers(
hass: HomeAssistant,
) -> dict[str, type[Trigger]]:
return {"off_to_on": _OffToOnTrigger}
mock_integration(hass, MockModule("test"))
mock_platform(hass, "test.trigger", Mock(async_get_triggers=async_get_triggers))
trigger_config = {
CONF_PLATFORM: "test.off_to_on",
CONF_TARGET: {CONF_ENTITY_ID: entity_ids},
CONF_OPTIONS: {ATTR_BEHAVIOR: behavior},
}
log = logging.getLogger(__name__)
@callback
def action(run_variables: dict[str, Any], context: Context | None = None) -> None:
calls.append(run_variables["trigger"])
@callback
def did_not_trigger(
run_variables: dict[str, Any],
info: NotTriggeredInfo,
context: Context | None = None,
) -> None:
did_not_trigger_reports.append(info)
validated_config = await async_validate_trigger_config(hass, [trigger_config])
return await async_initialize_triggers(
hass,
validated_config,
action,
domain="test",
name="test_off_to_on",
log_cb=log.log,
did_not_trigger=did_not_trigger,
)
async def test_entity_trigger_reports_did_not_trigger_behavior_all(
hass: HomeAssistant,
) -> None:
"""Behavior 'all' reports when not every targeted entity matches."""
entity_1 = "test.entity_1"
entity_2 = "test.entity_2"
hass.states.async_set(entity_1, STATE_OFF)
hass.states.async_set(entity_2, STATE_OFF)
await hass.async_block_till_done()
calls: list[dict[str, Any]] = []
did_not_trigger_reports: list[NotTriggeredInfo] = []
unsub = await _arm_off_to_on_trigger_with_diagnostics(
hass, [entity_1, entity_2], BEHAVIOR_ALL, calls, did_not_trigger_reports
)
# Only one of the two targets is on, so the trigger does not fire.
hass.states.async_set(entity_1, STATE_ON)
await hass.async_block_till_done()
assert calls == []
assert _reported_reasons(did_not_trigger_reports) == [
("not_all_targets_matched", {"matches": 1, "included": 2})
]
did_not_trigger_reports.clear()
# Now both targets are on, so the trigger fires and reports nothing further.
hass.states.async_set(entity_2, STATE_ON)
await hass.async_block_till_done()
assert len(calls) == 1
assert did_not_trigger_reports == []
unsub()
async def test_entity_trigger_reports_did_not_trigger_behavior_first(
hass: HomeAssistant,
) -> None:
"""Behavior 'first' reports when the number of matches isn't exactly one."""
entity_1 = "test.entity_1"
entity_2 = "test.entity_2"
hass.states.async_set(entity_1, STATE_OFF)
hass.states.async_set(entity_2, STATE_OFF)
await hass.async_block_till_done()
calls: list[dict[str, Any]] = []
did_not_trigger_reports: list[NotTriggeredInfo] = []
unsub = await _arm_off_to_on_trigger_with_diagnostics(
hass, [entity_1, entity_2], BEHAVIOR_FIRST, calls, did_not_trigger_reports
)
# The first target turns on: exactly one match, so the trigger fires.
hass.states.async_set(entity_1, STATE_ON)
await hass.async_block_till_done()
assert len(calls) == 1
assert did_not_trigger_reports == []
calls.clear()
# The second target turns on while the first is still on: two matches, no fire.
hass.states.async_set(entity_2, STATE_ON)
await hass.async_block_till_done()
assert calls == []
assert _reported_reasons(did_not_trigger_reports) == [
("behavior_first_not_satisfied", {"matches": 2})
]
unsub()
@pytest.mark.usefixtures("mock_integration_frame")
async def test_async_initialize_triggers_home_assistant_start_deprecated(
hass: HomeAssistant,