Files
LEDMatrix/.github/workflows/test.yml
T
Claude 2d6ff2bb88 feat(scroll): upstream the scroll orchestration layer; release 3.2.0
Phases B3 and B4.

B3 -- src/common/sports_scroll.py is deliberately NOT a superset of the
ten plugin scroll_display.py copies. A method-level comparison of the
eight that share a shape (f1 and ufc are genuine forks) found a sharp
split, and the module is drawn along it:

  promoted   orchestration -- get_all_vegas_content_items is identical
             in all eight; clear_all, get_scroll_info,
             get_dynamic_duration, is_complete and display_frame are
             96-100% similar
  promoted   settings -- one algorithm; the copies differ only in which
             league keys they walk, so the ladder is data
             (SCROLL_LEAGUE_KEYS) rather than a body per sport
  NOT        content -- prepare_scroll_content has 8 distinct bodies
             across 8 plugins (145 lines, 53% similar at worst) and
             _load_separator_icons 7 (6% at worst)

Same name, different job: prepare_scroll_content draws *this sport's*
game card. Merging those eight bodies would be exactly the mistake the
promotion rule exists to prevent, so the base raises NotImplementedError
rather than rendering something plausible -- a base that rendered
something would let a plugin ship a silently blank scroll.

The one behavior added over the plugin copies is native
global_config['target_fps'] support. The bundled copies hardcode ~100
FPS via scroll_delay and never consult the global target; Part A
threaded it through each copy by hand, and this makes that threading
legacy compatibility rather than the mechanism.

66 tests, including three against the real ScrollHelper rather than a
double -- a suite built entirely on MagicMock would sail straight past a
rename in the helper.

B4 -- bump src/__init__.py to 3.2.0 and close the CHANGELOG's Unreleased
section against it. This is the number the sunset rule keys on: the
first core release shipping the unified sports library, and therefore
the floor a plugin sets ledmatrix_min_version to before deleting its
bundled copies. The version bump and the changelog release heading move
together on purpose -- separating them would leave a commit whose
changelog announces 3.2.0 while the code still reports 3.1.0.

Nothing here changes what an existing plugin loads; adoption is B5.

Gates: 714 core unit, 66 plugin safety.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FgbA8SMutQQpXkMG8LMmC4
2026-08-01 17:02:20 +00:00

80 lines
2.6 KiB
YAML

name: Tests
on:
pull_request:
push:
branches: [main]
# Both jobs only check out the repo and run pytest.
permissions:
contents: read
jobs:
plugin-safety:
name: Plugin safety harness + unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: "3.12"
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt -r requirements-test.txt
pip install RGBMatrixEmulator
- name: Run harness + visual rendering tests
run: |
pytest --no-cov \
test/plugins/test_harness.py \
test/plugins/test_visual_rendering.py \
test/plugins/test_plugin_matrix.py
unit-tests:
name: Core unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: "3.12"
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt -r requirements-test.txt
pip install RGBMatrixEmulator
# Safety net for the shared sports/scroll/style infrastructure. These
# suites existed but were not enrolled in CI, so a refactor of
# src/base_classes or src/common could regress them silently. Enrolled
# explicitly (not `pytest test/`) so known hardware-only suites don't
# break CI; grow this list as more suites are made headless.
- name: Run core unit suites
run: |
pytest --no-cov \
test/test_skin_system.py \
test/test_font_manager.py \
test/test_data_sources.py \
test/test_api_extractors.py \
test/test_scroll_helper.py \
test/test_scroll_helper_continuous.py \
test/test_adaptive_layout.py \
test/test_loader_compat_warning.py \
test/test_sports_base_characterization.py \
test/test_element_style.py \
test/test_sports_core_promotions.py \
test/test_sports_modes_promotions.py \
test/test_sports_capabilities.py \
test/test_sports_scroll.py