Skip to content

Commit ba58e03

Browse files
authored
feat: CI fail-fast gating and post-test light teardown (#709)
Two improvements: 1. CI: lint and dependency-check now gate the test matrix. If either fails, test-core and test-cli are skipped rather than burning 18 matrix slots on code that won't pass review anyway. 2. Tests: session-scoped autouse fixture turns off all connected lights after the test session completes. Prevents lights activated during tests from staying on. Authored by Jny
1 parent 2c728d7 commit ba58e03

3 files changed

Lines changed: 60 additions & 5 deletions

File tree

.github/workflows/ci.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ jobs:
5252
5353
test-core:
5454
name: "Core: Tests (${{ matrix.python-version }}, ${{ matrix.os }})"
55-
needs: [detect-changes, get-python-versions]
56-
if: needs.detect-changes.outputs.core == 'true'
55+
needs: [detect-changes, get-python-versions, lint, dependency-check]
56+
if: |
57+
always()
58+
&& needs.detect-changes.outputs.core == 'true'
59+
&& needs.lint.result == 'success'
60+
&& (needs.dependency-check.result == 'success' || needs.dependency-check.result == 'skipped')
5761
runs-on: ${{ matrix.os }}
5862
strategy:
5963
fail-fast: false
@@ -84,8 +88,12 @@ jobs:
8488

8589
test-cli:
8690
name: "CLI: Tests (${{ matrix.python-version }}, ${{ matrix.os }})"
87-
needs: [detect-changes, get-python-versions]
88-
if: needs.detect-changes.outputs.cli == 'true' || needs.detect-changes.outputs.core == 'true'
91+
needs: [detect-changes, get-python-versions, lint, dependency-check]
92+
if: |
93+
always()
94+
&& (needs.detect-changes.outputs.cli == 'true' || needs.detect-changes.outputs.core == 'true')
95+
&& needs.lint.result == 'success'
96+
&& (needs.dependency-check.result == 'success' || needs.dependency-check.result == 'skipped')
8997
runs-on: ${{ matrix.os }}
9098
strategy:
9199
fail-fast: false

packages/busylight-core/tests/conftest.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
"""Test configuration and shared fixtures."""
22

3+
import gc
4+
35
import pytest
46
from serial.tools.list_ports_common import ListPortInfo
57

68
from busylight_core.hardware import Hardware
9+
from busylight_core.light import Light
710

811

912
@pytest.fixture
@@ -89,3 +92,22 @@ def hardware_devices(
8992
:return: List containing both mock Hardware instances
9093
"""
9194
return [hardware_hid_device, hardware_serial_device]
95+
96+
97+
@pytest.fixture(autouse=True, scope="session")
98+
def turn_off_lights_after_tests() -> None:
99+
"""Turn off all connected lights after the test session completes.
100+
101+
Finds any Light instances left open by tests and turns them off
102+
before releasing their hardware handles.
103+
"""
104+
yield # type: ignore[misc]
105+
106+
gc.collect()
107+
for obj in gc.get_objects():
108+
try:
109+
if isinstance(obj, Light) and obj.hardware.is_acquired:
110+
obj.off()
111+
obj.release()
112+
except Exception: # noqa: S110
113+
pass
Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,26 @@
1-
""" """
1+
"""Test configuration and shared fixtures."""
2+
3+
import gc
4+
5+
import pytest
6+
7+
from busylight_core.light import Light
8+
9+
10+
@pytest.fixture(autouse=True, scope="session")
11+
def turn_off_lights_after_tests() -> None:
12+
"""Turn off all connected lights after the test session completes.
13+
14+
Finds any Light instances left open by tests and turns them off
15+
before releasing their hardware handles.
16+
"""
17+
yield # type: ignore[misc]
18+
19+
gc.collect()
20+
for obj in gc.get_objects():
21+
try:
22+
if isinstance(obj, Light) and obj.hardware.is_acquired:
23+
obj.off()
24+
obj.release()
25+
except Exception: # noqa: S110
26+
pass

0 commit comments

Comments
 (0)