mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-07 11:48:06 +00:00
ci: run the whole test tree and make the plugin-safety job assert something real
The unit-tests CI job ran an explicit 24-file allowlist that had rotted: 63 of 90 test files (display, vegas, store manager, web API, web_interface) never ran on a PR. The job now runs all of test/ (minus test/plugins, which the plugin-safety job owns) so new test files are enrolled by default and any exclusion needs a visible, commented --ignore. The plugin-safety job was a green no-op: plugins/ is empty in CI, so every test skipped with 'Manifest not found'. It now renders a bundled deterministic fixture plugin (test/fixtures/plugins/ci-fixture-plugin, golden images included for all 8 default sizes) via LEDMATRIX_PLUGINS_DIR, and sets LEDMATRIX_REQUIRE_PLUGINS=1 so discovering zero plugins fails loudly instead of skipping green. The per-plugin suites document that they target dev machines with real plugins installed. Coverage is now measured and enforced in exactly one place — the CI unit-tests step (--cov=src --cov=web_interface --cov-fail-under=45, from a measured 47% baseline). pytest.ini previously declared --cov-fail-under=30 but CI always passed --no-cov, so the gate had never run anywhere; local pytest is now coverage-free and fast. Enabling the 63 unenrolled files surfaced three cases of test rot, fixed here: test_display_controller_vegas_tick.py could not collect without the hardware rgbmatrix module (now uses the emulator convention), the state-reconciliation unrecoverable-cache tests broke when production added the is_plugin_uninstalled tombstone check (bare Mock returned truthy), and test_get_system_status assumed the optional psutil dependency (now installed via requirements-test.txt and guarded by importorskip). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NohXi78cwsAKtN1sCfxjUh
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
CI fixture plugin.
|
||||
|
||||
Exists so the plugin safety harness (test/plugins/test_plugin_matrix.py and
|
||||
the plugin-safety CI job) always has at least one real plugin to load and
|
||||
render — without it, an empty plugins/ directory turns the whole job into a
|
||||
green no-op. The render is deliberately trivial and fully deterministic:
|
||||
a border rectangle plus both diagonals, sized from the display manager's
|
||||
declared dimensions. No fonts, no network, no time dependence, so golden
|
||||
images are stable across platforms.
|
||||
"""
|
||||
|
||||
from PIL import ImageDraw
|
||||
|
||||
from src.plugin_system.base_plugin import BasePlugin
|
||||
|
||||
|
||||
class CIFixturePlugin(BasePlugin):
|
||||
def update(self) -> None:
|
||||
"""Nothing to fetch — the render is self-contained."""
|
||||
|
||||
def display(self, force_clear: bool = False) -> None:
|
||||
width = self.display_manager.matrix.width
|
||||
height = self.display_manager.matrix.height
|
||||
border = tuple(self.config.get("border_color", [0, 255, 0]))
|
||||
diagonal = tuple(self.config.get("diagonal_color", [255, 0, 0]))
|
||||
|
||||
image = self.display_manager.image
|
||||
draw = ImageDraw.Draw(image)
|
||||
# Blank only the declared panel area, then draw edge-to-edge content:
|
||||
# the border proves the plugin reads dynamic dimensions (any overflow
|
||||
# or underfill at any size is a harness bug or a dimensions bug), the
|
||||
# diagonals make golden comparisons sensitive to size/offset drift.
|
||||
draw.rectangle([0, 0, width - 1, height - 1], fill=(0, 0, 0))
|
||||
draw.rectangle([0, 0, width - 1, height - 1], outline=border)
|
||||
draw.line([0, 0, width - 1, height - 1], fill=diagonal)
|
||||
draw.line([0, height - 1, width - 1, 0], fill=diagonal)
|
||||
self.display_manager.update_display()
|
||||
Reference in New Issue
Block a user