mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-06-29 23:38:38 +00:00
* feat(web): add Tools tab and row address type setting Adds a Tools/Utilities tab to the web interface with one-click maintenance buttons that previously required SSH: - Git status panel (branch, dirty state, recent commits) - Pull latest (rebase) and force reset to origin/main - Reinstall base requirements (pip, with output) - Reinstall per-plugin requirements (pass/fail per plugin) - Clear __pycache__ directories - Quick-access restart for display and web services Also exposes the hzeller row_address_type option (0–4) in the Display settings tab. The backend already read this value from config; the UI, API field list, and validation were missing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tools-tab): address code review findings - Add _GIT = shutil.which('git') alongside _SUDO/_JOURNALCTL; return 503 in force_git_reset and get_git_info if git is unavailable - Check git branch/status returncodes in get_git_info(); return a clear 500 error instead of silently treating a failed run as a clean repo - Cap pip stdout+stderr at 50 KB via _truncate_output() helper to avoid OOM on verbose dependency resolution or build failures - Scrub embedded HTTPS credentials from remote_url via _scrub_git_remote_url() using urllib.parse before returning to UI - Fix clear_pycache to track and report failed deletions separately instead of counting them as successes (removed ignore_errors=True, wrapped in try/except OSError) Skipped: plugin_manager-vs-api_v3.plugin_manager (api_v3 is the Blueprint object; accessing .plugin_manager on it would fail — module- level variable is the correct pattern used throughout this blueprint); pages_v3 broad-except (identical to every other _load_*_partial in the file); base.html HTMX fallback (loadTabContent handles all tabs generically; named fallbacks only exist for tabs needing JS re-init); tools.html auth (pre-existing architectural decision — reboot/shutdown on the same endpoint are also unauthenticated). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tools-tab): resolve remaining PR review comments - api_v3: use getattr(api_v3, 'plugin_manager', None) instead of the module-level plugin_manager (always None); app.py sets the blueprint attribute, not the module global, so the fallback to plugin-repos was always taken - pages_v3: replace broad except Exception in _load_tools_partial with specific TemplateNotFound / OSError handlers and add [Pages V3][Tools] context prefix to log messages and error responses for easier Pi debugging - base.html: add Tools tab branch to the HTMX-unavailable fallback block in loadTabContent so the tab loads gracefully via direct fetch if HTMX never initialises Skipped: auth on execute_system_action — pre-existing app-wide design; reboot/shutdown and all other system actions share the same exposure. An app-level auth layer is the correct fix and is out of scope here. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tools-tab): resolve second-pass review findings - Wrap per-plugin subprocess.run in try/except TimeoutExpired/OSError so one plugin's failure appends a result entry and continues the loop rather than collapsing the whole batch into a 500 - Validate double_sided_copies divisibility against chain_length (horizontal axis) or parallel (vertical axis) after the range check; reads effective axis from the current request or stored config - Exclude double_sided_fields from the generic key-merge loop so double_sided_enabled/copies/axis are never written as root-level keys - Fix tools.html copy: "then restores the stash" removed — git_pull stashes changes but never pops them - Check r.ok and d.status in loadGitInfo before building the panel; backend error messages now surface instead of silently showing a false-clean state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tools-tab): don't expose filesystem paths in OSError messages CodeQL flagged str(exc) flowing into the JSON response for the install_plugin_requirements action. Use exc.strerror instead, which gives the OS error description ("No such file or directory", "Permission denied") without the internal filesystem path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Chuck <chuck@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
50 KiB
50 KiB