Skip to content

Auction the hot seat instead of assigning it (#654) #657

Auction the hot seat instead of assigning it (#654)

Auction the hot seat instead of assigning it (#654) #657

Workflow file for this run

name: tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
pytest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
# Node is required for the worker ⇄ integration contract check
# (cf-workers/contract-check.mjs + `node --check`). ubuntu-latest ships
# node by default, but pinning it makes the gate deterministic so the
# QUIZIFY_REQUIRE_NODE=1 hard-fail below can never be undermined by a
# runner image that happens to drop node (#328).
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install deps
run: |
python -m pip install --upgrade pip
# Installs the lightweight test deps plus Home Assistant + the
# custom-component test harness (pytest-homeassistant-custom-component)
# so the HA-dependent modules (config_flow, binary_sensor) are
# importable and their tests actually run here (issue #271). HA is a
# heavy dep, kept scoped to this test job only.
pip install -r requirements_test.txt
- name: Run tests
# Enforce the worker-contract gate: a missing node here is a hard
# FAILURE, not a silent skip, so the cross-language check can't rot
# behind a perpetual skip (#313, #328).
env:
QUIZIFY_REQUIRE_NODE: "1"
run: pytest tests/ -v
- name: Byte-compile component (catches syntax errors)
run: |
python -m compileall -q custom_components/quizify
lint:
# Ruff lint gate (issue #306). The code was ruff-annotated by discipline
# (# noqa markers, zero bare except) but nothing enforced it β€” regressions
# went unflagged. Config + scoped ruleset live in pyproject.toml; the
# selected ruleset (E4/E7/E9 + F + I) passes on current main.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install ruff
run: pip install "ruff==0.15.17"
- name: Ruff lint
run: ruff check custom_components/
mypy:
# Static type-check gate (issue #328). Pragmatic, NOT --strict: the
# [tool.mypy] config in pyproject.toml catches real type errors (wrong
# types, Optional-init mistakes) while scoping ignore_missing_imports to
# the HA/aiohttp stack so framework typing gaps don't red the gate.
# Home Assistant is installed so its config-entry / metaclass typing
# (e.g. ConfigFlow's `domain=` __init_subclass__ kwarg) resolves β€” without
# it mypy can't see the framework base classes and flags a false positive.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install mypy + runtime/framework deps
run: |
python -m pip install --upgrade pip
# HA (+ its transitive aiohttp/voluptuous) so framework imports
# resolve; capped < 2026.3 to stay on the 3.13-compatible line, same
# constraint the test job uses. mypy pinned for a deterministic gate.
pip install "homeassistant<2026.3" "mypy==1.13.0"
- name: mypy type-check
run: mypy
drift:
# Generated-artifact-drift guard (issue #306). player.bundle.js / styles.css
# are committed but generated from www/js/ and www/css/src/ modules. The
# cache-buster fingerprints whatever bytes are on disk β€” it cannot detect a
# source-module change that was never rebuilt. This job rebuilds in CI and
# fails if the committed artifacts are stale. (tests/ also carries a unit
# counterpart, test_generated_artifacts_in_sync.py, run by the pytest job.)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Rebuild generated front-end artifacts
run: |
python scripts/build_bundle.py
python scripts/build_css.py
- name: Fail if committed artifacts are stale
run: |
if ! git diff --exit-code -- \
custom_components/quizify/www/js/player.bundle.js \
custom_components/quizify/www/css/styles.css; then
echo "::error::Generated artifacts are out of sync with their source modules."
echo "Run: python3 scripts/build_bundle.py && python3 scripts/build_css.py, then commit."
exit 1
fi