From a0466bf273dd8d22ae5e7fc3f5fe946ff5630ba6 Mon Sep 17 00:00:00 2001 From: Hpsaturn Date: Thu, 25 Jun 2026 01:10:52 +0200 Subject: [PATCH 1/4] added basic GitHub action for test possible pull requests --- .github/workflows/pull-request.yml | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/pull-request.yml diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000..9fb90d3 --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,85 @@ +name: Pull Request CI + +on: + pull_request: + branches: [ "main", "master" ] + +jobs: + test-desktop: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libsdl2-2.0-0 libsdl2-ttf-2.0-0 libsdl2-image-2.0-0 + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install pygame + + - name: Translate source (English) + run: | + python tools/translate.py --lang en src build/desktop-en + + - name: Verify translated output + run: | + test -f build/desktop-en/main_desktop.py + echo "Translation OK" + + - name: Headless import test + shell: bash + run: | + cd build/desktop-en + export SDL_VIDEODRIVER=dummy + export SDL_AUDIODRIVER=dummy + python3 << 'PYEOF' + import os, sys, types + + for mod in ('espnow_manager', 'espnow_handler', 'visit_manager', + 'sleep_manager', 'wifi_tracker', 'machine'): + sys.modules[mod] = types.ModuleType(mod) + + import json + sys.modules['ujson'] = json + sys.modules['uos'] = os + + import pygame + pygame.init() + + import config_desktop + sys.modules['config'] = config_desktop + + import renderer_desktop + sys.modules['renderer'] = renderer_desktop + + import input_desktop + sys.modules['input'] = input_desktop + + import framebuf + + from context import GameContext + from scene_manager import SceneManager + from weather_system import WeatherSystem + from time_system import TimeSystem + from splash import show_splash + + print('All game modules imported successfully') + pygame.quit() + PYEOF + + - name: Headless game smoke test + shell: bash + run: | + export SDL_VIDEODRIVER=dummy + export SDL_AUDIODRIVER=dummy + timeout 8 python run.py --lang en || true From 7ba03064a59c1695727cd04c1b802bf8c4c597a4 Mon Sep 17 00:00:00 2001 From: Hpsaturn Date: Thu, 25 Jun 2026 01:38:32 +0200 Subject: [PATCH 2/4] testing screenshot upload artifact --- .github/workflows/pull-request.yml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 9fb90d3..48376de 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -25,7 +25,7 @@ jobs: - name: Install Python dependencies run: | python -m pip install --upgrade pip - pip install pygame + pip install pygame pillow - name: Translate source (English) run: | @@ -77,9 +77,23 @@ jobs: pygame.quit() PYEOF - - name: Headless game smoke test + - name: Headless game smoke test (with screenshot) shell: bash run: | export SDL_VIDEODRIVER=dummy export SDL_AUDIODRIVER=dummy - timeout 8 python run.py --lang en || true + python run.py --lang en --screenshot + # Verify screenshot was created + if [ -f build/desktop-en/screenshot.png ]; then + echo "Screenshot captured: $(file build/desktop-en/screenshot.png)" + else + echo "Warning: screenshot not found" + fi + + - name: Upload screenshot artifact + uses: actions/upload-artifact@v4 + if: always() + with: + name: game-screenshot + path: build/desktop-en/screenshot.png + if-no-files-found: warn From 5eb5eae0fdcd3459523a7a94758d0e0aaac13641 Mon Sep 17 00:00:00 2001 From: Hpsaturn Date: Thu, 25 Jun 2026 01:44:36 +0200 Subject: [PATCH 3/4] added new feature to take screenshots for CI artifact --- .github/workflows/pull-request.yml | 4 ++-- run.py | 3 +++ src/main_desktop.py | 33 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 48376de..1bad26d 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -1,8 +1,8 @@ name: Pull Request CI on: - pull_request: - branches: [ "main", "master" ] + push: + branches: '**' jobs: test-desktop: diff --git a/run.py b/run.py index d0e4d73..773daa6 100644 --- a/run.py +++ b/run.py @@ -17,6 +17,7 @@ def main(): parser = argparse.ArgumentParser(description='Run Catode32 desktop emulator.') parser.add_argument('--lang', default='en', help='Language code (default: en)') + parser.add_argument('--screenshot', action='store_true', help='Capture a screenshot after boot and save as screenshot.png') args = parser.parse_args() root = os.path.dirname(os.path.abspath(__file__)) @@ -35,6 +36,8 @@ def main(): env = os.environ.copy() env['CATODE32_SRC'] = src_dir + if args.screenshot: + env['CATODE32_SCREENSHOT'] = '1' os.execve(sys.executable, [sys.executable, main_script], env) diff --git a/src/main_desktop.py b/src/main_desktop.py index 1cbca1e..fe682b5 100644 --- a/src/main_desktop.py +++ b/src/main_desktop.py @@ -22,6 +22,14 @@ import pygame pygame.init() +# ── Screenshot support (optional, enabled via CATODE32_SCREENSHOT env var) ── +_SCREENSHOT_ENABLED = os.environ.get('CATODE32_SCREENSHOT') == '1' +_SCREENSHOT_FRAME = 30 # capture after this many frames +_SCREENSHOT_COUNTER = 0 +_SCREENSHOT_PATH = os.path.join( + os.path.dirname(os.path.abspath(__file__)), 'screenshot.png' +) + # ── Swap in desktop versions before anything else imports the originals ── # We rename the desktop modules to the names the game expects. import config_desktop @@ -96,6 +104,21 @@ def _ticks_diff(a, b): from splash import show_splash import config +# ── Screenshot helper ────────────────────────────────────────────────────── +def _save_screenshot(surface): + """Save the pygame surface as a PNG file.""" + try: + from PIL import Image + # pygame surface -> raw RGB bytes -> PIL Image + raw = pygame.image.tostring(surface, 'RGB') + img = Image.frombytes('RGB', surface.get_size(), raw) + img.save(_SCREENSHOT_PATH) + print(f"==> Screenshot saved: {_SCREENSHOT_PATH} " + f"({surface.get_width()}x{surface.get_height()})") + except Exception as e: + print(f"[Screenshot] Failed: {e}") + + # ── Game class (trimmed version of main.py — no ESP-Now, no deep sleep) ─── class Game: @@ -155,6 +178,16 @@ def run(self): self.scene_manager.draw() self.renderer.show() + # ── screenshot capture (CI only) ────────────────────────── + global _SCREENSHOT_COUNTER + if _SCREENSHOT_ENABLED: + _SCREENSHOT_COUNTER += 1 + if _SCREENSHOT_COUNTER == _SCREENSHOT_FRAME: + _save_screenshot(self.renderer.display._surface) + if _SCREENSHOT_ENABLED: + print("==> Screenshot captured, auto-quitting...") + self._quit() + self.last_frame_time = now clock.tick(config.FPS) From 5d93333284990cd8bd39e4d746c2c3cf8fe19751 Mon Sep 17 00:00:00 2001 From: Hpsaturn Date: Thu, 25 Jun 2026 02:02:47 +0200 Subject: [PATCH 4/4] added basic badge for pull request GitHub action --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b8dabc2..ab07e5f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Catode32 - A virtual pet for your ESP32 +[![Dekstop](https://github.com/moonbench/catode32/actions/workflows/pull-request.yml/badge.svg)](https://github.com/moonbench/catode32/actions/workflows/pull-request.yml) + ![catstars](https://github.com/user-attachments/assets/2ffc652a-f392-42e7-9a13-d7fb91f3770d) ![spookycat](https://github.com/user-attachments/assets/c1f8b6eb-b90c-46ad-b652-80093db97f83)