docs(scripts): monorepo workspace layout; fix_perms and install READMEs

MULTI_ROOT_WORKSPACE_SETUP described one sibling repository per plugin;
setup_plugin_repos.py links ../ledmatrix-plugins/plugins/* into
plugin-repos/ and update_plugin_repos.py pulls only the monorepo, and the
workspace file opens LEDMatrix plus ../ledmatrix-plugins.

scripts/fix_perms/README.md listed cache directories
fix_cache_permissions.sh never touches and a 'ledmatrix' service user
that doesn't exist (also in scripts/install/README.md); adds
safe_pip_install.sh. install/README: install_service.sh installs the web
and update-verify units too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-17 09:05:00 -04:00
co-authored by Claude Opus 5
parent 4d9c52f182
commit f2241f3938
3 changed files with 105 additions and 108 deletions
+80 -95
View File
@@ -1,169 +1,154 @@
# Multi-Root Workspace Setup Guide # Multi-Root Workspace Setup Guide
This document explains how the LEDMatrix project uses a multi-root workspace to manage plugins as separate Git repositories. This document explains how to work on LEDMatrix and the official plugins side
by side, with one editor workspace and the plugins loaded straight from your
plugin checkout.
## Overview ## Overview
The LEDMatrix project has been migrated from a git submodule implementation to a **multi-root workspace** implementation for managing plugins. This allows: Official plugins live in a single repository,
[ledmatrix-plugins](https://github.com/ChuckBuilds/ledmatrix-plugins), with one
directory per plugin under `plugins/`. There are no separate per-plugin
repositories. For development you clone that monorepo **next to** LEDMatrix
and symlink its plugin directories into LEDMatrix's `plugin-repos/`, which is
where the plugin loader looks by default.
- ✅ Plugins to exist as independent Git repositories - ✅ Plugin code stays in the monorepo checkout, with its own git history
- ✅ Updates to plugins without modifying the LEDMatrix project - ✅ LEDMatrix discovers the plugins through symlinks in `plugin-repos/`
- ✅ Easy development workflow with all repos in one workspace - ✅ `LEDMatrix.code-workspace` opens both repositories in VS Code/Cursor
- ✅ Plugin system discovers plugins via symlinks in `plugin-repos/`
## Directory Structure ## Directory Structure
```text ```text
/home/chuck/Github/ ~/Github/
├── LEDMatrix/ # Main project ├── LEDMatrix/ # Main project
│ ├── plugin-repos/ # Symlinks to actual repos (managed automatically) │ ├── plugin-repos/ # Plugin directory the loader scans
│ │ ├── ledmatrix-clock-simple -> ../../ledmatrix-clock-simple │ │ ├── starlark-apps/ # Bundled with LEDMatrix (tracked in git)
│ │ ├── ledmatrix-weather -> ../../ledmatrix-weather │ │ ├── web-ui-info/ # Bundled with LEDMatrix (tracked in git)
│ │ ├── clock-simple -> ../../ledmatrix-plugins/plugins/clock-simple
│ │ ├── ledmatrix-weather -> ../../ledmatrix-plugins/plugins/ledmatrix-weather
│ │ └── ... │ │ └── ...
│ ├── LEDMatrix.code-workspace # Multi-root workspace configuration │ ├── LEDMatrix.code-workspace # Opens LEDMatrix and ../ledmatrix-plugins
│ └── ... │ └── ...
├── ledmatrix-clock-simple/ # Plugin repository (actual git repo) └── ledmatrix-plugins/ # Plugin monorepo (git repo)
├── ledmatrix-weather/ # Plugin repository (actual git repo) ├── plugins/
├── ledmatrix-football-scoreboard/ # Plugin repository (actual git repo) │ ├── clock-simple/
└── ... # Other plugin repos │ ├── ledmatrix-weather/
│ └── ...
├── plugins.json # Store registry
└── update_registry.py
``` ```
## How It Works ## How It Works
### 1. Plugin Repositories ### 1. The plugin monorepo
All plugin repositories are cloned to `/home/chuck/Github/` (parent directory of LEDMatrix) as regular Git repositories: Clone ledmatrix-plugins into the same parent directory as LEDMatrix (the
scripts below look for `../ledmatrix-plugins` relative to the LEDMatrix
root):
- `ledmatrix-clock-simple/` ```bash
- `ledmatrix-weather/` cd ~/Github
- `ledmatrix-football-scoreboard/` git clone https://github.com/ChuckBuilds/ledmatrix-plugins.git
- etc. ```
### 2. Symlinks in plugin-repos/ ### 2. Symlinks in plugin-repos/
The `LEDMatrix/plugin-repos/` directory contains symlinks pointing to the actual repositories in the parent directory. This allows the plugin system to discover plugins without modifying the project structure. `scripts/setup_plugin_repos.py` creates one symlink per plugin in
`LEDMatrix/plugin-repos/`, named after the plugin's manifest `id` and pointing
at `../ledmatrix-plugins/plugins/<dir>`.
### 3. Multi-Root Workspace ### 3. Multi-root workspace
The `LEDMatrix.code-workspace` file configures VS Code/Cursor to open all plugin repositories as separate workspace roots, allowing easy development across all repos. `LEDMatrix.code-workspace` has two roots: LEDMatrix itself and
`../ledmatrix-plugins`.
## Setup Scripts ## Setup Scripts
### Initial Setup ### Initial Setup
If you already have plugin repositories cloned, use the setup script:
```bash ```bash
cd /home/chuck/Github/LEDMatrix cd ~/Github/LEDMatrix
python3 scripts/setup_plugin_repos.py python3 scripts/setup_plugin_repos.py
``` ```
This script: This script:
- Reads the workspace configuration - Reads each `manifest.json` under `../ledmatrix-plugins/plugins/`
- Creates symlinks in `plugin-repos/` pointing to actual repos - Creates `plugin-repos/<id>` symlinks (relative) to those directories
- Verifies all links are created correctly - Leaves correct links alone, replaces links that point elsewhere, and skips
(does not overwrite) a real directory of the same name — for example a
plugin you installed from the Plugin Store. Remove that directory first if
you want the linked copy.
### Updating Plugins ### Updating Plugins
To update all plugin repositories:
```bash ```bash
cd /home/chuck/Github/LEDMatrix cd ~/Github/LEDMatrix
python3 scripts/update_plugin_repos.py python3 scripts/update_plugin_repos.py
``` ```
This script: This runs `git pull` in `../ledmatrix-plugins` and prints the result. The
- Finds all plugins in the workspace symlinks pick up the new code; restart the display to load it.
- Runs `git pull` on each repository
- Reports which plugins were updated
## Configuration ## Configuration
The plugin system is configured in `config/config.json`: The loader reads plugins from `plugin_system.plugins_directory` in
`config/config.json`. The default is already right for this setup:
```json ```json
{ {
"plugin_system": { "plugin_system": {
"plugins_directory": "plugin-repos", "plugins_directory": "plugin-repos"
"auto_discover": true,
"auto_load_enabled": true
} }
} }
``` ```
The `plugins_directory` points to `plugin-repos/`, which contains symlinks to the actual repositories.
## Workflow ## Workflow
### Daily Development ### Daily Development
1. **Open Workspace**: Open `LEDMatrix.code-workspace` in VS Code/Cursor 1. **Open Workspace**: Open `LEDMatrix.code-workspace` in VS Code/Cursor
2. **All Repos Available**: All plugin repos appear as separate folders in the workspace 2. **Edit Plugins**: Edit code under `ledmatrix-plugins/plugins/<plugin>/`
3. **Edit Plugins**: Edit plugin code directly in their repositories 3. **Test**: `python3 run.py -e` (emulator) or
4. **Update Plugins**: Run `update_plugin_repos.py` to pull latest changes `python3 scripts/check_plugin.py --plugin <id>` from LEDMatrix
4. **Ship**: Bump `version` in the plugin's `manifest.json`, run
`python update_registry.py` in ledmatrix-plugins, commit there
### Adding New Plugins ### Adding New Plugins
1. **Clone Repository**: Clone the new plugin repo to `/home/chuck/Github/` 1. Create `plugins/<your-plugin-id>/` in the monorepo checkout
2. **Add to Workspace**: Add the plugin folder to `LEDMatrix.code-workspace` 2. Run `python3 scripts/setup_plugin_repos.py` in LEDMatrix to link it
3. **Create Symlink**: Run `setup_plugin_repos.py` to create the symlink
### Updating Individual Plugins
Since plugins are regular Git repositories, you can update them individually:
```bash
cd /home/chuck/Github/ledmatrix-weather
git pull origin master
```
Or update all at once:
```bash
cd /home/chuck/Github/LEDMatrix
python3 scripts/update_plugin_repos.py
```
## Benefits
1. **No Submodule Hassle**: No need to update `.gitmodules` or run `git submodule update`
2. **Independent Updates**: Update plugins independently without touching LEDMatrix
3. **Clean Separation**: Each plugin is a separate repository with its own history
4. **Easy Development**: Multi-root workspace makes it easy to work across repos
5. **Automatic Discovery**: Plugin system automatically discovers plugins via symlinks
## Troubleshooting ## Troubleshooting
### Symlinks Not Working ### Plugins not discovered
If plugins aren't being discovered:
```bash ```bash
cd /home/chuck/Github/LEDMatrix cd ~/Github/LEDMatrix
python3 scripts/setup_plugin_repos.py ls -la plugin-repos/ # links present and not broken?
python3 scripts/setup_plugin_repos.py # recreate them
``` ```
This will recreate all symlinks. Also check that `plugin_system.plugins_directory` is `plugin-repos`.
### Missing Plugins ### "Monorepo plugins directory not found"
If a plugin is in the workspace but not found: `setup_plugin_repos.py` expects the monorepo at `../ledmatrix-plugins`. Clone
it there (or symlink it there).
1. Check if the repo exists in `/home/chuck/Github/` ### Plugin updates not showing
2. Check if the symlink exists in `plugin-repos/`
3. Run `setup_plugin_repos.py` to recreate symlinks
### Plugin Updates Not Showing 1. Verify the link target: `ls -la plugin-repos/<id>`
2. Check that you're editing the monorepo checkout, not a store-installed copy
If changes to plugins aren't appearing: 3. Restart the LEDMatrix service (or `run.py`)
1. Verify the symlink points to the correct directory: `ls -la plugin-repos/ledmatrix-weather`
2. Check that you're editing in the actual repo, not a copy
3. Restart the LEDMatrix service if running
## Notes ## Notes
- The `plugin-repos/` directory is tracked in git, but only contains symlinks - `plugin-repos/` is tracked in git only for the bundled plugins
- Actual plugin code lives in `/home/chuck/Github/ledmatrix-*/` (`starlark-apps`, `web-ui-info`). The symlinks you create are untracked
- Each plugin repo can be updated independently via `git pull` files; don't commit them.
- The LEDMatrix project doesn't need to be updated when plugins change - For linking a single plugin into `plugins/` instead (without a sibling
checkout), see `scripts/dev/dev_plugin_setup.sh` in the
[Plugin Development Guide](PLUGIN_DEVELOPMENT_GUIDE.md).
- When changing a plugin in the monorepo, bump its manifest `version` and run
`python update_registry.py`, or users won't receive the update.
+15 -7
View File
@@ -7,8 +7,10 @@ install as the wrong user, after a manual file copy that didn't preserve
ownership, or after a permissions-related error from the display or ownership, or after a permissions-related error from the display or
web service. web service.
Most of these scripts require `sudo` since they touch directories Most of these scripts require `sudo` since they touch directories owned
owned by the `ledmatrix` service user or by `root`. by `root` (the display service's user) or by the user you installed
LEDMatrix as (the web service's user). There is no dedicated `ledmatrix`
system user.
## Scripts ## Scripts
@@ -16,11 +18,12 @@ owned by the `ledmatrix` service user or by `root`.
permissions on the `assets/` tree so plugins can download and cache permissions on the `assets/` tree so plugins can download and cache
team logos, fonts, and other static content. team logos, fonts, and other static content.
- **`fix_cache_permissions.sh`** — Fixes permissions on every cache - **`fix_cache_permissions.sh`** — Creates (if missing) and fixes
directory the project may use (`/var/cache/ledmatrix/`, permissions on `/var/cache/ledmatrix/` and `~/.ledmatrix_cache/` of the
`~/.cache/ledmatrix/`, `/opt/ledmatrix/cache/`, project-local user running `sudo`, and creates
`cache/`). Also creates placeholder logo subdirectories used by the `/var/cache/ledmatrix/placeholder_logos/` for the sports plugins. It does
sports plugins. not touch the cache manager's other fallbacks (`/opt/ledmatrix/cache`,
`$TMPDIR/ledmatrix_cache`).
- **`fix_plugin_permissions.sh`** — Fixes ownership on the plugins - **`fix_plugin_permissions.sh`** — Fixes ownership on the plugins
directory so both the root display service and the web service user directory so both the root display service and the web service user
@@ -31,6 +34,11 @@ owned by the `ledmatrix` service user or by `root`.
systemd journal access, and the sudoers entries the web interface systemd journal access, and the sudoers entries the web interface
needs to control the display service. needs to control the display service.
- **`safe_pip_install.sh`** — Installs a `requirements.txt` as root
after checking it is the project's own or one under `plugin-repos/` or
`plugins/`. Used by the web interface (via sudo) to install plugin
dependencies where `ledmatrix.service` can import them.
- **`safe_plugin_rm.sh`** — Validates that a plugin removal path is - **`safe_plugin_rm.sh`** — Validates that a plugin removal path is
inside an allowed base directory before deleting it. Used by the web inside an allowed base directory before deleting it. Used by the web
interface (via sudo) when a user clicks **Uninstall** on a plugin — interface (via sudo) when a user clicks **Uninstall** on a plugin —
+9 -5
View File
@@ -7,14 +7,18 @@ This directory contains scripts for installing and configuring the LEDMatrix sys
- **`one-shot-install.sh`** - Single-command installer; clones the - **`one-shot-install.sh`** - Single-command installer; clones the
repo, checks prerequisites, then runs `first_time_install.sh`. repo, checks prerequisites, then runs `first_time_install.sh`.
Invoked via `curl ... | bash` from the project root README. Invoked via `curl ... | bash` from the project root README.
- **`install_service.sh`** - Installs the main LED Matrix display service (systemd) - **`install_service.sh`** - Installs, enables and starts the display
- **`install_web_service.sh`** - Installs the web interface service (systemd) service (`ledmatrix.service`), the web interface service
(`ledmatrix-web.service`) and the update-verify units (systemd)
- **`install_web_service.sh`** - Installs only the web interface service
and the update-verify units (systemd)
- **`install_wifi_monitor.sh`** - Installs the WiFi monitor daemon service - **`install_wifi_monitor.sh`** - Installs the WiFi monitor daemon service
- **`setup_cache.sh`** - Sets up persistent cache directory with proper permissions - **`setup_cache.sh`** - Sets up persistent cache directory with proper permissions
- **`configure_web_sudo.sh`** - Configures passwordless sudo access for web interface actions - **`configure_web_sudo.sh`** - Configures passwordless sudo access for web interface actions
- **`configure_wifi_permissions.sh`** - Grants the `ledmatrix` user - **`configure_wifi_permissions.sh`** - Grants the web interface's user
the WiFi management permissions needed by the web interface and (the user who runs the script, i.e. the one you installed LEDMatrix as;
the WiFi monitor service there is no `ledmatrix` system user) the passwordless `nmcli` and related
WiFi permissions the web interface needs
- **`migrate_config.sh`** - Migrates configuration files to new formats (if needed) - **`migrate_config.sh`** - Migrates configuration files to new formats (if needed)
- **`debug_install.sh`** - Diagnostic helper used when an install - **`debug_install.sh`** - Diagnostic helper used when an install
fails; collects environment info and recent logs fails; collects environment info and recent logs