Files
Kiwy-Signage/.github/instructions/kiwy-build-and-development.instructions.md
T
ske087 eb8e66e427 Add build and development instructions for the workspace
Document how to build, package and release the player so the knowledge is not
rediscovered on each machine or session.

New file: .github/instructions/kiwy-build-and-development.instructions.md

Contents:
- Entry points: src/main.py on Linux/Pi, windows/run_win.py on Windows (which
  patches platform differences before running main.py).
- Verified toolchain: Python 3.12.9 x64 in windows\venv, Kivy 2.3.1,
  PyInstaller 6.21.0. Python 3.13+/3.14 is unsupported for the Windows build
  because Kivy 2.3.1 has no wheels for them.
- Build commands (pyinstaller build.spec, build_win.bat) and the real output
  path, including the note that cefpython3 is not installed in this venv, so
  the embedded-CEF engine is inactive and web links use the subprocess adapter.
- build.spec expectations: runtime hook for DPI awareness, console=True,
  excludes, and the rule that lazily/dynamically imported modules must be listed
  in hiddenimports or the packaged exe fails with ModuleNotFoundError.
- Code signing constraint: production hosts enforce Smart App Control, where an
  unsigned (or self-signed) exe is blocked at kernel level, so a public CA cert
  is required.
- Verification: py_compile gate, the need to close the running player before a
  rebuild (output lock / "Access is denied"), the .exe reserved-device-name
  pitfall that makes Test-Path report a false positive without -LiteralPath, and
  the stale duplicate one-file exe at windows\dist\KiwySignagePlayer.exe that
  must not be deployed.
- Release checklist and commit hygiene (do not track dist/build output or the
  player_auth.json credential files).
2026-09-10 16:52:41 +03:00

6.3 KiB

description, name
description name
Use when building, compiling, packaging or releasing the Kiwy Signage Player: PyInstaller build, .exe generation, build.spec, hiddenimports, code signing, Smart App Control, Windows development, Raspberry Pi deployment, or adding new modules under src/. Covers the exact build commands, environment constraints, bundling rules and verification steps. Kiwy Build & Development

Kiwy Signage Player — Build & Development

Cross-platform Kivy digital signage player.

  • Raspberry Pi / Linuxsrc/main.py is the entry point (root install.sh, start.sh).
  • Windowswindows/run_win.py is the entry point; it sets Windows env vars, imports main.py, then monkey-patches platform differences. Packaged to .exe with PyInstaller.

Ground Rules

  • Keep src/main.py cross-platform. Windows-specific behaviour belongs in windows/run_win.py (see _patch_main()), Pi-specific behaviour in main.py guarded by capability checks. Do not add Windows-only imports to main.py.
  • Rebuild is mandatory. The .exe bundles src/, so Python edits are invisible until you rebuild. There is no hot reload in the packaged app.
  • dist/ is a runtime folder, not just build output. It holds config/, media/, playlists/, logs/, .kiosk-profile/ and .player_heartbeat. Never wipe dist/ blindly; a --clean rebuild preserves it, but a manual delete destroys player state.

Environment

Item Value
Interpreter Python 3.12.9 (64-bit) — project venv at windows\venv
Kivy 2.3.1
PyInstaller 6.21.0
Linux target Python 3.13 (repo/python-wheels/, repo/system-packages/)
  • Python 3.13+/3.14 is NOT supported for the Windows build — Kivy 2.3.1 has no wheels for them.
  • cefpython3 is not installed in the project venv. The embedded-CEF web-link engine is therefore unavailable and web links fall back to the Chrome/Edge subprocess adapter. Installing cefpython3 (uncomment it in windows/requirements_win.txt) restores the CEF engine.

Build

From windows\:

venv\Scripts\python.exe -m PyInstaller build.spec --clean --noconfirm

Or the full one-click path (creates venv, installs deps, builds, then signs):

build_win.bat

Output (folder mode, via COLLECT):

windows\dist\KiwySignagePlayer\KiwySignagePlayer.exe   <- the real build output

Deployment hazard: windows\dist\KiwySignagePlayer.exe (one level up) is a stale leftover from an older single-file build of the same name. It is not refreshed by the current spec, so deploying it ships old code. Always take the executable from the KiwySignagePlayer\ subfolder, and delete the stray copy if it reappears.

build.spec facts

  • Entry point run_win.py; pathex=[BUILD_DIR, SRC_DIR] so src/ modules resolve.
  • runtime_hooks=[pyi_runtime_hook.py] — sets per-monitor DPI awareness before SDL/Kivy initialise. Keep DPI work here; it must run before any window is created.
  • datas += Tree(src) bundles all of src/. console=True so startup errors and the Kivy log remain visible — do not flip this to False without a reason.
  • hiddenimports must list modules that PyInstaller's static analysis cannot see: lazily imported ones (cef_browser is imported inside a function) or dynamic imports (getattr, importlib). Top-level imports such as weblink_session are found automatically via pathex, but listing them is harmless insurance. When you add a module under src/ that is imported lazily or by string, add it to hiddenimports or the packaged exe will fail at runtime with ModuleNotFoundError.
  • excluded_imports drops Linux-only packages (evdev, gi, GStreamer) and the non-matching cefpython3 .pyd variants.

Code Signing (production constraint)

Production PCs run with Smart App Control enforced (VerifiedAndReputablePolicyState=1, UMCI enforced) with no "Run anyway" bypass — an unsigned exe is blocked at kernel level.

  • A self-signed certificate does NOT satisfy Smart App Control. A cert from a reputable public CA is required. create_self_signed_cert.ps1 is dev-only.
  • Provide a cert as KIWY_SIGN_PFX (+ optional KIWY_SIGN_PFX_PASSWORD) or drop kiwy_signing.pfx in windows\; build_win.bat then signs via sign_exe.ps1 (signtool with RFC3161 timestamp when available).
  • See documentation/CODE_SIGNING_SMART_APP_CONTROL.md.

Verify Before Committing

Fast syntax gate (no build, seconds):

python -m py_compile src/main.py src/weblink_session.py windows/run_win.py

Close the running player before rebuilding. A running dist\KiwySignagePlayer\KiwySignagePlayer.exe locks the output and the build fails with "Access is denied". Chrome/Edge kiosk processes left over from web-link playback can also hold locks; if the build fails, check for stray msedge.exe / chrome.exe before retrying.

Because .exe is a reserved Windows device name as well as a real file, use Test-Path -LiteralPath when probing for the executable, otherwise the path silently resolves to the console device.

Development run — use this on a SAC-locked host, since the unsigned exe cannot launch:

cd windows
venv\Scripts\activate
python run_win.py

Diagnose playback transitions via the trace log (logs\playback_trace.log), written by src/playback_trace.py.

Release Checklist

  1. Bump PLAYER_VERSION in src/main.py and filevers/prodvers/FileVersion/ ProductVersion in windows\version_info.txt; keep them in sync.
  2. Rebuild (build_win.bat).
  3. Confirm the exe is signed (Get-AuthenticodeSignature); unsigned builds are blocked on production hosts.
  4. Smoke-test a mixed playlist: image → video → weblink → image, verifying durations, audio (audio: off / muted), and a clean exit/restart.

Commit Hygiene

  • Never commit windows\build\ or windows\dist\ (git-ignored). Tracked build output such as windows\archive_list.txt and windows\build_last.txt is the exception, not the rule.
  • Do not commit player_auth.json or src/player_auth.json — they contain live credentials (auth_code, player_id, server_url). These are currently tracked; treat any future change to them as a deliberate, reviewed decision.
  • Do not commit config\app_config.json values that are host-specific without checking whether they belong in the repo default.