Auction the hot seat instead of assigning it (#654) #657
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |