mirror of
https://github.com/dmduran12/pymc_console-dist.git
synced 2026-10-31 01:42:00 +01:00
docs: retire standalone distribution and guide plugin migration
This commit is contained in:
1 parent
f4f761ad3c
commit
108a11dbee
3 files changed
+193
-844
No files matched your search
+143
-91
@@ -1,123 +1,175 @@
|
||||
# Installing waev:outpost
|
||||
# Installing and migrating to waev:outpost
|
||||
|
||||
This guide covers **manual** installation of the standalone waev:outpost dashboard (without `manage.sh`). For the standard installer workflow, see [README.md](README.md).
|
||||
New waev:outpost versions are delivered as the **waev.outpost application UI plugin** for [openHop Repeater](https://github.com/openhop-dev/openhop_repeater). **v0.9.394 is the final legacy standalone release** from `pymc_console-dist`. Existing standalone users can move to the plugin without uninstalling their old files or resetting Repeater.
|
||||
|
||||
> [!TIP]
|
||||
> **You probably don't need this page.** If your openHop Repeater has a **Plugins** page, open it, find **waev:outpost**, press **Install** and then **Enable**, and you're done. It will keep itself up to date from then on: when a new version is out, the version number at the top of the screen turns yellow, and one press of **Update** installs it. The steps below are only for a repeater without a Plugins page, or for people who want to place the files themselves.
|
||||
- [Install from the catalogue](#install-from-the-catalogue-recommended)
|
||||
- [Migrate an existing standalone installation](#migrate-from-the-standalone-install)
|
||||
- [Install a downloaded wheel](#install-a-plugin-wheel)
|
||||
- [Recover the built-in Repeater interface](#recovery)
|
||||
|
||||
## Prerequisite
|
||||
|
||||
An existing [openHop Repeater](https://github.com/openhop-dev/openhop_repeater) installation, 1.1 or newer; the console tracks the Repeater's `dev` branch and is checked against it before each release (see the README's Repeater compatibility section for what it reads and what it tolerates). waev:outpost is served by openHop Repeater's CherryPy server; installing it on its own does nothing useful.
|
||||
Use a working Repeater installation with application UI plugins and a running plugin manager. The instructions below describe the current built-in Repeater interface. Use your repeater's existing address; examples assume the default port, 8000.
|
||||
|
||||
Verify Repeater is installed:
|
||||
If **System → Plugins** is missing, update Repeater through its [supported installation or upgrade process](https://github.com/openhop-dev/openhop_repeater). On an existing native installation, the updated Repeater `manage.sh upgrade` must be run once as an administrator to replace the privileged upgrade helper; installing only a new Python wheel cannot replace that helper. See [Repeater's native upgrade prerequisite](https://github.com/openhop-dev/openhop_repeater/blob/dev/docs/plugins.md#native-upgrade-prerequisite).
|
||||
|
||||
If the Plugins page says **Plugin manager is unavailable**, resolve that before installing the UI plugin. On a native host, check `systemctl status openhop-plugin-manager`. Current Repeater Docker images run the manager alongside Repeater unless it is explicitly disabled. Use the same Plugins page in Docker and LXC; do not run the legacy standalone installer inside the container.
|
||||
|
||||
Repeater continues to own its radio settings, identities, credentials, database and service. UI plugin installation does not reset them. Keep using your existing Repeater login. A backend upgrade, if needed, is a separate operation from this UI migration.
|
||||
|
||||
## Install from the catalogue (recommended)
|
||||
|
||||
1. Open the **built-in Repeater interface** at your repeater's home address. If waev:outpost currently occupies that address, follow the [migration steps](#migrate-from-the-standalone-install) to switch interfaces first.
|
||||
2. Open **System → Plugins → Catalogue**.
|
||||
3. Find **waev:outpost** and press **Install**. Repeater downloads the approved wheel and verifies its checksum, plugin ID and version against the catalogue.
|
||||
4. Wait for completion. On the **Installed** tab, the UI plugin should show **UI READY**. Catalogue installation enables it automatically; if it is disabled, press **Enable**.
|
||||
5. Use **Open UI**, or visit `http://<repeater-ip>:8000/plugins/waev.outpost/`. Sign in with your existing Repeater credentials and check that you see your repeater and the expected version.
|
||||
|
||||
You can use the direct plugin address without changing the default interface.
|
||||
|
||||
## Make waev:outpost the default interface
|
||||
|
||||
In the **built-in Repeater interface**, open **System → Configuration → Access → Web Options → Web Frontend** and select the **waev:outpost plugin** entry. Selection applies immediately and refreshes the page. The repeater's home address, `/`, now serves waev:outpost.
|
||||
|
||||
If the old standalone files are still installed, the built-in interface also lists **openHop Console** at `/opt/pymc_console/web/html`. That is the legacy copy, not the plugin. Select the plugin entry to use new releases.
|
||||
|
||||
From current waev:outpost, the equivalent controls are **Configuration → Web Frontend**: select an interface, press **Set as default interface**, then **Open default interface in a new tab**. Apply or discard other configuration drafts before switching. The direct `/plugins/waev.outpost/` address continues to open the plugin even when another interface is the default.
|
||||
|
||||
## Migrate from the standalone install
|
||||
|
||||
This applies to copies installed from `pymc_console-dist`, its `manage.sh`, or the `pymc-ui-*` archives under `/opt/pymc_console/web/html`.
|
||||
|
||||
1. **Keep the existing files and Repeater configuration.** You do not need to uninstall waev:outpost, recreate your account, re-enter radio settings or remove `/opt/pymc_console`.
|
||||
2. In the existing waev:outpost, open **Configuration → Web Frontend**. Select **Default Frontend**, the built-in Repeater interface. In v0.9.394 the switch applies immediately and reloads. Newer waev versions ask you to press **Set as default interface** and offer **Open default interface in a new tab**. Open the home address `/` if you remain on the direct plugin address. If you cannot open the current UI, use [Recovery](#recovery).
|
||||
3. In the built-in interface, open **System → Plugins → Catalogue**, find **waev:outpost**, and press **Install**. Wait for **UI READY**, then open `/plugins/waev.outpost/` and confirm your connection and the installed version.
|
||||
4. Return to the built-in interface's **System → Configuration → Access → Web Options → Web Frontend** and select the **waev:outpost plugin** entry as the default.
|
||||
5. For subsequent releases, use the [plugin update controls](#keeping-it-up-to-date). The old standalone `manage.sh upgrade` does not migrate to the plugin and will not deliver new plugin versions.
|
||||
|
||||
The migration changes where Repeater serves its UI. Its configuration, identities and login credentials stay in place. Both interfaces use the same Repeater API. Keep the same protocol, host and port to retain access to your browser origin's saved preferences; there is no need to clear browser storage.
|
||||
|
||||
Leave the old standalone folder in place until you are satisfied with the plugin. To switch back to the built-in interface, select **Default Frontend**. To temporarily return to the old standalone copy, choose **openHop Console** in the built-in interface while that folder still exists. waev itself labels this choice **waev:outpost · standalone install**. Your old copy keeps its installed version; the standalone channel ends at v0.9.394.
|
||||
|
||||
<a id="manual-update"></a>
|
||||
|
||||
## Keeping it up to date
|
||||
|
||||
For catalogue installs:
|
||||
|
||||
1. In the built-in interface, open **System → Plugins → Catalogue** and press **Refresh**.
|
||||
2. If waev:outpost offers **Update**, press it and wait for the operation to finish.
|
||||
3. Reopen the plugin or refresh its page and check the version.
|
||||
|
||||
In waev:outpost, the version badge also opens **What's new**, with **Check** and **Update** when the repeater reports an available plugin update. Updates require your confirmation; they are not installed automatically.
|
||||
|
||||
A GitHub release is published before catalogue approval. Repeater offers the version approved in its catalogue, so a newer release may not appear immediately. Existing installations keep working if the catalogue is temporarily unavailable.
|
||||
|
||||
For a fresh local-wheel installation, use **Install wheel** again with the newer wheel as described below. The Repeater backend itself is upgraded separately through its own installer or container process.
|
||||
|
||||
<a id="2b-install-by-hand"></a>
|
||||
<a id="manual-install-no-managesh"></a>
|
||||
|
||||
## Install a plugin wheel
|
||||
|
||||
This is an alternative to catalogue installation, for example when you need a published version that is not yet approved in the catalogue.
|
||||
|
||||
1. Download the single `.whl` asset from the desired [waev-outpost-plugin release](https://github.com/Treehouse-00/waev-outpost-plugin/releases). Its name is `waev_outpost_plugin-<version>-py3-none-any.whl`.
|
||||
2. In the built-in interface, open **System → Plugins → Install wheel**.
|
||||
3. Choose the downloaded `.whl` file and press **Install**.
|
||||
4. If the plugin is disabled, press **Enable** on the Installed tab. Confirm **UI READY**, open its UI, and optionally [make it the default](#make-waevoutpost-the-default-interface).
|
||||
|
||||
A fresh wheel upload does not establish catalogue repository metadata. The automatic **Update** operation can therefore be unavailable; upload a newer wheel with **Install wheel** to update that installation. An upload over an existing catalogue-managed installation may retain that installation's provenance.
|
||||
|
||||
To move a fresh local-wheel installation onto catalogue-managed updates, reinstall the approved version through the [catalogue-install API](#automation). Check the catalogue version first: it may be older than the wheel you uploaded. Installing a local wheel does not make that version catalogue-approved.
|
||||
|
||||
## Recovery
|
||||
|
||||
If the current UI works, choose **Default Frontend** under its Web Frontend controls, then open the repeater's home address `/`. This is the built-in Repeater interface. Do this before disabling or uninstalling the currently selected plugin.
|
||||
|
||||
If the UI cannot be opened but the Repeater API is reachable, restore the built-in default with an existing authenticated API token:
|
||||
|
||||
```bash
|
||||
ls /opt/openhop_repeater/pyproject.toml
|
||||
REPEATER_URL='http://<repeater-ip>:8000'
|
||||
TOKEN='<repeater-api-token>'
|
||||
curl --fail-with-body -sS -X POST "$REPEATER_URL/api/update_web_config" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"web":{"web_path":null}}'
|
||||
```
|
||||
|
||||
On a system that still runs the pyMC-era layout (`/opt/pymc_repeater`, `/etc/pymc_repeater/config.yaml`, the `pymc-repeater` service), `manage.sh` detects it and patches that config file instead. openHop Repeater's own `manage.sh` migrates those paths to the openHop ones and retires the `pymc-repeater` service the next time you run its install or upgrade, and the Console's `web_path` setting moves with the config. The paths below are the current openHop ones.
|
||||
Replace the placeholders with your repeater address and token. Read the response: confirm success and persistence, and follow `restart_required` if reported. Reopen `/`; a hard refresh may be needed. This changes only the default UI selection, not credentials or radio settings. There is no separate `/builtin` recovery URL.
|
||||
|
||||
---
|
||||
If you cannot authenticate to the API, use administrator access to the host and Repeater's configuration/credential recovery process. For a native installation, restoring `web.web_path` to YAML `null` in the existing `/etc/openhop_repeater/config.yaml` and restarting `openhop-repeater` selects the built-in interface. Keep the rest of that configuration intact. For Docker or older pyMC-era paths, use the actual mounted configuration and service for that installation instead of assuming the native path.
|
||||
|
||||
## Using manage.sh (Recommended)
|
||||
If plugin operations fail with an unavailable manager, see [Prerequisite](#prerequisite). A missing plugin manager does not itself stop Repeater's normal radio operation.
|
||||
|
||||
## Automation
|
||||
|
||||
Use an existing Repeater API token. Replace the placeholders before running these commands:
|
||||
|
||||
```bash
|
||||
git clone --depth 1 --single-branch --branch main --no-tags \
|
||||
https://github.com/Treehouse-00/pymc_console-dist.git pymc_console
|
||||
cd pymc_console
|
||||
sudo ./manage.sh install
|
||||
REPEATER_URL='http://<repeater-ip>:8000'
|
||||
TOKEN='<repeater-api-token>'
|
||||
|
||||
# Inspect the catalogue and its currently approved versions.
|
||||
curl --fail-with-body -sS "$REPEATER_URL/api/plugins/catalogue" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Install the approved waev:outpost version; this also enables it.
|
||||
curl --fail-with-body -sS -X POST "$REPEATER_URL/api/plugins/catalogue_install" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"id":"waev.outpost"}'
|
||||
|
||||
# Check for an approved update for the installed plugin.
|
||||
curl --fail-with-body -sS "$REPEATER_URL/api/plugins/updates?id=waev.outpost" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Apply the update when one is available.
|
||||
curl --fail-with-body -sS -X POST "$REPEATER_URL/api/plugins/update" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"id":"waev.outpost"}'
|
||||
```
|
||||
|
||||
Use the shallow public distribution clone to avoid downloading historical UI
|
||||
builds. The installer downloads the current UI release separately. This does
|
||||
not remove objects already downloaded by an existing full clone; re-clone once
|
||||
after the latest-only migration to reclaim that space.
|
||||
Inspect each response for success before continuing. The update endpoint needs repository metadata; use the catalogue-install operation to establish it for a fresh local-wheel installation.
|
||||
|
||||
This downloads the latest waev:outpost release, extracts to `/opt/pymc_console/web/html`, and — on a fresh install, when `yq` is present — patches `web.web_path` in `/etc/openhop_repeater/config.yaml`. Without `yq` the dashboard is still installed and the installer prints the command to run by hand. See [README.md](README.md) for all commands.
|
||||
|
||||
---
|
||||
|
||||
## Manual Install (no manage.sh)
|
||||
|
||||
If you don't want to clone this repo, install the release tarball directly:
|
||||
To upload a wheel instead of installing from the catalogue:
|
||||
|
||||
```bash
|
||||
# 1. Download the latest waev:outpost release
|
||||
cd /tmp
|
||||
wget https://github.com/Treehouse-00/pymc_console-dist/releases/latest/download/pymc-ui-latest.tar.gz
|
||||
curl --fail-with-body -sS -X POST "$REPEATER_URL/api/plugins/install" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F 'wheel=@/path/to/waev_outpost_plugin-<version>-py3-none-any.whl'
|
||||
|
||||
# 2. Extract to /opt/pymc_console/web/html (the waev:outpost install target)
|
||||
sudo mkdir -p /opt/pymc_console/web/html
|
||||
sudo tar -xzf pymc-ui-latest.tar.gz -C /opt/pymc_console/web/html/
|
||||
|
||||
# 3. Set ownership to the repeater service user
|
||||
sudo chown -R repeater:repeater /opt/pymc_console
|
||||
|
||||
# 4. Point openHop Repeater at the dashboard (one-time)
|
||||
# Open /etc/openhop_repeater/config.yaml and set:
|
||||
# web:
|
||||
# web_path: /opt/pymc_console/web/html
|
||||
# Or, if you have `yq` installed:
|
||||
sudo yq -i '.web.web_path = "/opt/pymc_console/web/html"' /etc/openhop_repeater/config.yaml
|
||||
|
||||
# 5. Restart the repeater service
|
||||
sudo systemctl restart openhop-repeater
|
||||
|
||||
# 6. Clean up
|
||||
rm /tmp/pymc-ui-latest.tar.gz
|
||||
curl --fail-with-body -sS -X POST "$REPEATER_URL/api/plugins/enable" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"id":"waev.outpost"}'
|
||||
```
|
||||
|
||||
The dashboard is now served at `http://<your-pi-ip>:8000/`.
|
||||
|
||||
---
|
||||
|
||||
## Manual Update
|
||||
|
||||
To update an existing waev:outpost install without using `manage.sh`:
|
||||
After confirming the plugin works at `/plugins/waev.outpost/`, select it as the default:
|
||||
|
||||
```bash
|
||||
# Download latest version
|
||||
cd /tmp
|
||||
wget https://github.com/Treehouse-00/pymc_console-dist/releases/latest/download/pymc-ui-latest.tar.gz
|
||||
|
||||
# Backup existing dashboard
|
||||
sudo cp -r /opt/pymc_console/web/html /opt/pymc_console/web/html.backup
|
||||
|
||||
# Replace contents (web_path is preserved since we keep the same directory)
|
||||
sudo rm -rf /opt/pymc_console/web/html/*
|
||||
sudo tar -xzf pymc-ui-latest.tar.gz -C /opt/pymc_console/web/html/
|
||||
sudo chown -R repeater:repeater /opt/pymc_console
|
||||
|
||||
# Clean up
|
||||
rm /tmp/pymc-ui-latest.tar.gz
|
||||
curl --fail-with-body -sS -X POST "$REPEATER_URL/api/update_web_config" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"web":{"web_path":"plugin:waev.outpost"}}'
|
||||
```
|
||||
|
||||
No service restart is required for asset-only updates — clients will pick up the new bundle on next page load. Hard-refresh (`Cmd+Shift+R` / `Ctrl+Shift+R`) if stale.
|
||||
|
||||
---
|
||||
|
||||
## Only the latest release is published
|
||||
|
||||
Each release replaces the previous one on the distribution repository: the
|
||||
sync workflow deletes every older release and tag, so there is no versioned
|
||||
download to pin and no way to install an earlier UI. The current release does
|
||||
carry a `pymc-ui-v<tag>` archive, but it disappears with the release it belongs
|
||||
to. `releases/latest/download/` is the only supported source.
|
||||
|
||||
---
|
||||
The stable `plugin:waev.outpost` reference follows the installed plugin version. Confirm success, persistence and any restart requirement in the response. To restore the built-in default, use the same endpoint with `{"web":{"web_path":null}}`.
|
||||
|
||||
## Uninstall
|
||||
|
||||
```bash
|
||||
sudo rm -rf /opt/pymc_console
|
||||
First restore **Default Frontend** and confirm the repeater's home address opens the built-in UI. Then use **System → Plugins → Installed → Uninstall** for waev:outpost. Leave **Also delete persistent data directory** unchecked to keep plugin data for a later reinstall. Repeater's own configuration and radio service are separate.
|
||||
|
||||
# Clear web.web_path yourself when it still points at the dashboard you just
|
||||
# removed, so the Repeater falls back to upstream's Vue.js dashboard instead of
|
||||
# serving nothing. A value you set by hand to something else is left for you to
|
||||
# change. (`manage.sh uninstall` does this step for you.)
|
||||
sudo yq -i 'del(.web.web_path)' /etc/openhop_repeater/config.yaml
|
||||
Do not remove `/opt/pymc_console` as part of plugin installation or migration. It is the independent legacy copy and can remain available for switching back.
|
||||
|
||||
sudo systemctl restart openhop-repeater
|
||||
```
|
||||
<a id="using-managesh-recommended"></a>
|
||||
<a id="only-the-latest-release-is-published"></a>
|
||||
|
||||
openHop Repeater itself is not affected.
|
||||
## Legacy standalone reference
|
||||
|
||||
The final standalone assets are retained at [v0.9.394](https://github.com/Treehouse-00/pymc_console-dist/releases/tag/v0.9.394). They belong to the retired standalone channel. New installs and upgrades should use the plugin instructions above.
|
||||
|
||||
A legacy installation normally consists of `/opt/pymc_console/web/html`, a separate source or installer checkout such as `~/pymc_console`, and `web.web_path` pointing to that UI directory. Its old `manage.sh install`, `upgrade` and `uninstall` commands manage those files, not Repeater plugins.
|
||||
|
||||
No legacy cleanup is required to use the plugin. If you later choose to remove the old files, first confirm the default UI uses the plugin or built-in interface and retain any backup you need. The old `manage.sh uninstall` also offers to remove its checkout, so read its prompts. Keep Repeater's own installation, configuration and data intact.
|
||||
@@ -1,468 +1,53 @@
|
||||
<p align="center">
|
||||
<img src="docs/images/waev-outpost-card.jpg" alt="waev:outpost, the Outpost paint over a star field above the companion instrument's hardware bank" width="100%">
|
||||
</p>
|
||||
# waev:outpost — legacy standalone distribution
|
||||
|
||||
<h1 align="center">waev:outpost</h1>
|
||||
> **This standalone distribution is retired. v0.9.394 is its final release.**
|
||||
> New waev:outpost updates are delivered through the [waev:outpost Repeater plugin](https://github.com/Treehouse-00/waev-outpost-plugin). Start with [plugin release v0.9.396](https://github.com/Treehouse-00/waev-outpost-plugin/releases/tag/v0.9.396), or install the currently approved version from Repeater's catalogue.
|
||||
|
||||
<p align="center"><strong>A retro-futuristic operations console for <a href="https://meshcore.io/">MeshCore</a> LoRa mesh repeaters.</strong></p>
|
||||
Your existing standalone installation can continue to run. The [v0.9.394 downloads](https://github.com/Treehouse-00/pymc_console-dist/releases/tag/v0.9.394) remain available. Installing the plugin does not require deleting `/opt/pymc_console`, resetting Repeater, changing radio settings or replacing your credentials.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Treehouse-00/waev-outpost-plugin/releases"><img alt="Plugin release" src="https://img.shields.io/github/v/release/Treehouse-00/waev-outpost-plugin?label=plugin&color=2f7d4f"></a>
|
||||
<a href="https://github.com/Treehouse-00/pymc_console-dist/releases"><img alt="Standalone release" src="https://img.shields.io/github/v/release/Treehouse-00/pymc_console-dist?label=standalone"></a>
|
||||
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
||||
</p>
|
||||
## Move to the plugin
|
||||
|
||||
<p align="center">
|
||||
<a href="#quick-start">Quick start</a> ·
|
||||
<a href="#product-tour">Tour</a> ·
|
||||
<a href="#install">Install</a> ·
|
||||
<a href="#following-releases">Releases</a> ·
|
||||
<a href="#troubleshooting">Troubleshooting</a> ·
|
||||
<a href="#development">Development</a>
|
||||
</p>
|
||||
Use your existing repeater address; the examples below assume the default port, 8000.
|
||||
|
||||
---
|
||||
1. **Open the built-in Repeater interface.** In the legacy waev:outpost console, open **Configuration → Web Frontend** and select **Default Frontend**, the built-in Repeater interface. In v0.9.394 the change applies immediately and reloads the page. If needed, open the repeater's home address, `http://<repeater-ip>:8000/`.
|
||||
2. **Install from the catalogue.** In the built-in interface, open **System → Plugins → Catalogue**, find **waev:outpost**, and press **Install**. Catalogue installation enables it automatically.
|
||||
3. **Check the plugin.** On the **Installed** tab, confirm **UI READY**. If it is disabled, press **Enable**. Use **Open UI**, or open `http://<repeater-ip>:8000/plugins/waev.outpost/`, and sign in with your existing Repeater credentials. Check the installed version and connection to your repeater.
|
||||
4. **Make it the default.** Return to the built-in interface and open **System → Configuration → Access → Web Options → Web Frontend**. Select the **waev:outpost plugin** entry. The selection applies immediately; the repeater's home address now serves the plugin.
|
||||
|
||||
waev:outpost turns the live API and packet stream of an [openHop Repeater](https://github.com/openhop-dev/openhop_repeater) into one browser workspace: a map of the mesh, a packet lab, RF and noise-floor analytics, host telemetry, and a companion chat. It is a static web application that the repeater serves itself. Nothing else to run, nothing to patch.
|
||||
If the old folder is still installed, the built-in interface also lists **openHop Console** at `/opt/pymc_console/web/html`. That is the old standalone copy. Choose the plugin entry for new releases.
|
||||
|
||||
waev:outpost was pyMC Console and then openHop Console. The repository, the `/opt/pymc_console` install directory and the `pymc-ui-*` archive names keep the old name, so existing installs and scripts keep working.
|
||||
Your Repeater configuration, radio identities and login credentials stay in place. Keep the same protocol, host and port to retain access to that browser origin's saved preferences. The old standalone folder can remain as a fallback; no uninstall is needed.
|
||||
|
||||

|
||||
If **System → Plugins** is missing or the plugin manager is unavailable, [update Repeater and check its plugin prerequisites](INSTALL.md#prerequisite) before proceeding. The old standalone installer does not provide plugin support.
|
||||
|
||||
## Features at a glance
|
||||
## Install a downloaded wheel instead
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Retro-futuristic UI** | Keycaps, seven-segment readouts, LED meters and amber screen wells. Every page is an instrument, not a form. Dark and light, desktop and phone. |
|
||||
| **Advanced mesh mapping** | 3D terrain, live traces, hop meters, and Viterbi path disambiguation that resolves colliding two-character prefixes to real nodes. |
|
||||
| **Robust system stats** | Load, storage, heat and I/O on the front plate; CPU, memory, NVMe and sensor envelopes underneath, live. |
|
||||
| **Local network I/O** | TX and RX rate scopes with peak hold, plus bytes and packets since boot. |
|
||||
| **Noise-floor visualization and anomaly detection** | A density scatter of the floor across days, with tunable percentile thresholds that flag interference bursts. |
|
||||
| **Robust packet filtering** | Type, route, status, signal, node class, free text and a time slider, all stacking. |
|
||||
| **Mesh analytics with packet throughput** | Forwarded versus dropped by packet type over time, with duplicate rate, CRC failures and LBT wait. |
|
||||
| **Public hash channel detection** | Hashed group channels recognised and named as they appear on air, decrypted where the key is known. |
|
||||
| **Packet parsing with duplicate scanning** | A byte-level Wire Inspector that maps every field to its bytes, resolves the path on a map, and walks the copies of a flood. |
|
||||
| **Companion chat** | Message the mesh straight from your repeater through a companion identity: channels and DMs, bot cards, reply, and an outbound queue meter. |
|
||||
To install a specific published plugin version, download its single `.whl` asset from [waev-outpost-plugin releases](https://github.com/Treehouse-00/waev-outpost-plugin/releases).
|
||||
|
||||
## Quick start
|
||||
In the built-in interface, use **System → Plugins → Install wheel**, choose the file and press **Install**. Press **Enable** if disabled, confirm **UI READY**, and test `/plugins/waev.outpost/`. Select the plugin under **Web Options → Web Frontend** if you want it at `/`.
|
||||
|
||||
> [!TIP]
|
||||
> **Three presses and you're in.** If your openHop Repeater has a **Plugins** page (repeaters from September 2026 do), open it, find **waev:outpost**, press **Install**, then **Enable**. That's it.
|
||||
A fresh local-wheel installation has no catalogue repository metadata, so the automatic **Update** operation may be unavailable. Update it by uploading a newer wheel with **Install wheel** again. To adopt catalogue-managed updates, use the [catalogue-install API](INSTALL.md#automation) to reinstall the approved version. Check that version first because it may be older than a manually uploaded wheel.
|
||||
|
||||
Open `http://<repeater-ip>:8000/plugins/waev.outpost/` and sign in with the same username and password you use for the repeater. Prefer waev:outpost at the repeater's front door, `http://<repeater-ip>:8000/`? Choose it as the repeater's web interface on the same Plugins page.
|
||||
## Future updates
|
||||
|
||||
Installed this way, it looks after itself. When a new version is out, the version number at the top of the screen turns yellow. Tap it, press **Update**, and the repeater installs the new version and reloads the page for you.
|
||||
- **Catalogue installation:** in the built-in interface, use **System → Plugins → Catalogue → Refresh**, then **Update** when offered. In waev:outpost, the version badge also offers **What's new → Check / Update** when the repeater reports an available plugin update.
|
||||
- **Fresh local-wheel installation:** upload the newer wheel with **Install wheel** again, or adopt catalogue installation as described above.
|
||||
- **Legacy standalone installation:** this repository ends at v0.9.394. Its old `manage.sh upgrade` does not install or update the plugin.
|
||||
|
||||
No Plugins page on your repeater? This repository is the other way in: a small script that installs waev:outpost by hand. Read on under [Install](#install).
|
||||
Updates require your confirmation. A published GitHub release becomes available through the catalogue only after approval, so the catalogue may temporarily offer an earlier version. Repeater itself is upgraded separately through its own supported installer or container process.
|
||||
|
||||
## Product tour
|
||||
## Switch back or recover
|
||||
|
||||
### The instrument
|
||||
In current waev:outpost, open **Configuration → Web Frontend**, select **Default Frontend**, press **Set as default interface**, then **Open default interface in a new tab**. The direct `/plugins/waev.outpost/` address still opens the plugin; use `/` to see the selected default.
|
||||
|
||||

|
||||
To temporarily return to your old standalone copy, select **openHop Console** in the built-in interface while `/opt/pymc_console/web/html` still exists. waev labels this choice **waev:outpost · standalone install**. Your old copy keeps its installed version; the standalone channel ends at v0.9.394.
|
||||
|
||||
The console is built as hardware. Node classes are keycaps with their own counters. Zoom, view and basemap are keys on the right rail. Hop distribution is an LED column meter. The screen well carries the map with a CRT-style bezel, and the whole plate carries the identity of the node it is bolted to. The same parts kit, the TUI Kit, builds every other page, so once you have learned one panel you have learned them all.
|
||||
If the UI cannot be opened, follow [Recovery](INSTALL.md#recovery) to restore the built-in default through the authenticated Repeater API or the host's existing configuration. Switch to a working default before disabling or uninstalling the selected plugin. Do not delete Repeater's configuration or data.
|
||||
|
||||
### Mesh cartography
|
||||
## Downloads and documentation
|
||||
|
||||
- MapLibre GL rendering with CARTO basemaps and 3D terrain from elevation tiles
|
||||
- Repeaters, hubs, neighbours, rooms and your own node, filtered by class and link quality
|
||||
- **Deep Analysis**: a Viterbi hidden Markov model picks the most probable path when a two-character prefix matches several nodes, weighing recency, co-occurrence, position, geography and measured edges
|
||||
- **Live Trace**: packets animate along their resolved path as they arrive
|
||||
- Ghost-node discovery for prefixes that never resolve, with RF-constrained location estimates
|
||||
- Wardrive replay, GPS diagnostics, and a searchable contact inventory in the same workspace
|
||||
|
||||
### Packet lab
|
||||
|
||||

|
||||
|
||||
The throughput chart splits traffic into what the repeater forwarded and what it dropped, per packet type, across the selected window. The counters above it are the ones that matter for a repeater: forwarded, dropped, duplicate rate, CRC failures, and mean listen-before-talk wait.
|
||||
|
||||

|
||||
|
||||
Filters stack. Pick a node class, a route type, a delivery status and a signal band, then narrow to a node by name and scrub the time slider. The same filter engine drives the Packets page and the Statistics analyzer, so a selection means the same thing everywhere.
|
||||
|
||||

|
||||
|
||||
The **Wire Inspector** opens any packet down to its bytes. Header, hashes, path and payload are colour-mapped, and clicking a decoded field highlights the bytes that produced it. The path is resolved and drawn on a map with a confidence score per hop. When a flood arrives more than once, the copies are listed together so you can compare the routes they took.
|
||||
|
||||
### RF health
|
||||
|
||||

|
||||
|
||||
The noise floor is sampled continuously and drawn as a density scatter, so a week of readings shows its shape rather than a smeared average. Daily bands make diurnal patterns obvious.
|
||||
|
||||

|
||||
|
||||
**Anomaly detection** watches the floor for sustained rises above a baseline. Baseline and spike percentiles, merge gap, minimum sequence length and similarity tolerance are sliders, and the resulting configuration is printed so it can be shared. Detected anomalies are counted and overlaid on the packet analyzer, which plots every packet by type across the window, as totals or as airtime.
|
||||
|
||||
### Channels
|
||||
|
||||

|
||||
|
||||
Group text on MeshCore travels under a channel hash. The console recognises the hashes that appear on air, names the ones it knows from its curated geographic and community channel list, and decrypts traffic for any channel whose key it holds. The dashboard shows chat activity per channel over the selected window.
|
||||
|
||||
### Companion chat
|
||||
|
||||

|
||||
|
||||
Create a companion identity on the repeater and the console becomes a messenger: no second radio, you talk to the mesh straight from your openHop node. Channels and direct messages sit in an amber LED screen with a contact roster, unread tallies, reply and delete on every message, and bot responses printed as instrument cards. The plate above it carries the companion selector, flood and zero-hop advert keys, the channel and contact counters, an outbound queue meter, and LINK, RX and TX lamps.
|
||||
|
||||
### Host telemetry
|
||||
|
||||

|
||||
|
||||
The System workspace reads the host the repeater runs on. Load, storage, heat and network I/O are seven-segment readouts. CPU and memory are a live scope. Temperature envelopes cover the SoC and every NVMe drive, and memory and storage are column meters. Sensors, logs, storage, recovery, diagnostics and a terminal are tabs in the same workspace.
|
||||
|
||||

|
||||
|
||||
Local network I/O is a two-channel scope for the host's interface, with peak hold, current rates on the readouts, and bytes and packets since boot.
|
||||
|
||||
### Dashboard
|
||||
|
||||

|
||||
|
||||
The home dashboard is the one-glance view: live traffic and recent packets, chat activity, mesh health, SpamGuard, and node context. On wide displays it becomes a pane-of-glass layout. Tap the version badge for the release notes.
|
||||
|
||||
---
|
||||
|
||||
## Install
|
||||
|
||||
### Two ways in
|
||||
|
||||
| Your repeater | How waev:outpost gets there | How it updates |
|
||||
|---|---|---|
|
||||
| Has a **Plugins** page | Install it from that page. [Step 2a](#2a-install-from-the-repeaters-plugins-page-recommended) | On its own. Press **Update** when the version number turns yellow. |
|
||||
| Has no Plugins page | Run the `manage.sh` script from this repository. [Step 2b](#2b-install-by-hand) | `sudo bash manage.sh upgrade` |
|
||||
| Runs in a **Proxmox LXC** | Create the container with the [openHop LXC installer](https://github.com/openhop-dev/openhop_repeater#proxmox-lxc-installation), then follow 2a or 2b. | As above |
|
||||
| Runs in **Docker** | The `main` and `dev` images of `openhop/openhop-repeater` already include the matching waev:outpost. Nothing to install. | With the image |
|
||||
|
||||
### 1. Install openHop Repeater
|
||||
|
||||
waev:outpost requires a working Repeater backend. Follow the [openHop Repeater installation guide](https://github.com/openhop-dev/openhop_repeater), or use its installer:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/openhop-dev/openhop_repeater.git
|
||||
cd openhop_repeater
|
||||
sudo bash ./manage.sh install
|
||||
```
|
||||
|
||||
Repeater owns the Python environment, radio and GPIO setup, `/etc/openhop_repeater/config.yaml`, authentication, and the `openhop-repeater` systemd service.
|
||||
|
||||
### 2a. Install from the repeater's Plugins page (recommended)
|
||||
|
||||
Your repeater can install waev:outpost for you, the same way a phone installs an app. Nothing to download, nothing to copy, and nothing written anywhere except the repeater's own plugin folder.
|
||||
|
||||
1. Open the repeater's web interface and go to **Configuration → Plugins**.
|
||||
2. Find **waev:outpost** in the list of available plugins and press **Install**. The repeater fetches the package from [waev-outpost-plugin](https://github.com/Treehouse-00/waev-outpost-plugin), checks that it is genuine, and installs it.
|
||||
3. Press **Enable**.
|
||||
4. Open `http://<repeater-ip>:8000/plugins/waev.outpost/` and sign in. If you'd like waev:outpost to be what you see at `http://<repeater-ip>:8000/`, choose it as the repeater's web interface on the same page.
|
||||
|
||||
#### Keeping it up to date
|
||||
|
||||
You don't have to do anything. waev:outpost quietly asks the repeater every so often whether a newer version is available. When one is:
|
||||
|
||||
1. The version number at the top of the screen turns **yellow**.
|
||||
2. Tap it to open **What's new**, and press **Update**.
|
||||
3. The repeater installs the new version while you watch, then reloads the page.
|
||||
|
||||
There's a **Check** button on the same screen if you'd rather ask right away, and the repeater's own Plugins page offers the same update.
|
||||
|
||||
> [!NOTE]
|
||||
> A brand-new release takes a little while to reach your repeater's plugin list. If you've just seen an announcement and nothing appears yet, check back later.
|
||||
|
||||
<details>
|
||||
<summary><strong>From a script instead</strong></summary>
|
||||
|
||||
The same steps are available from the API with a repeater token:
|
||||
|
||||
```bash
|
||||
curl -X POST http://<repeater-ip>:8000/api/plugins/catalogue_install \
|
||||
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
|
||||
-d '{"id": "waev.outpost"}'
|
||||
curl -X POST http://<repeater-ip>:8000/api/plugins/enable \
|
||||
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
|
||||
-d '{"id": "waev.outpost"}'
|
||||
```
|
||||
|
||||
`POST /api/plugins/update` with the same body installs an update.
|
||||
|
||||
</details>
|
||||
|
||||
### 2b. Install by hand
|
||||
|
||||
For a repeater without a Plugins page, or if you'd rather keep the files yourself under `/opt/pymc_console`. On the repeater itself:
|
||||
|
||||
```bash
|
||||
cd ~
|
||||
git clone --depth 1 --single-branch --branch main --no-tags \
|
||||
https://github.com/Treehouse-00/pymc_console-dist.git pymc_console
|
||||
cd pymc_console
|
||||
sudo bash manage.sh install
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><strong>Why a shallow clone?</strong></summary>
|
||||
|
||||
It saves space on small hosts. Each release replaces the public branch with one snapshot, so prior releases and their history are not reachable from this repository. The checkout holds the installer and the documentation; the built files come from the current GitHub release. An older full clone keeps objects it already downloaded, so re-clone once to reclaim that space.
|
||||
|
||||
</details>
|
||||
|
||||
The script:
|
||||
|
||||
1. Verifies that openHop Repeater is installed.
|
||||
2. Downloads the latest `pymc-ui-latest.tar.gz` release.
|
||||
3. Extracts the static app to `/opt/pymc_console/web/html/`.
|
||||
4. On a fresh install, sets `web.web_path` in `/etc/openhop_repeater/config.yaml` when `yq` is available.
|
||||
5. Leaves Repeater, Core, radio configuration, and service lifecycle untouched.
|
||||
|
||||
Open `http://<repeater-ip>:8000/` and sign in with the credentials configured for Repeater.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Port 8000 is meant for a trusted LAN or VPN. Do not expose the repeater's API and waev:outpost directly to the public internet.
|
||||
|
||||
Prefer to place the files yourself? [INSTALL.md](INSTALL.md) walks through it.
|
||||
|
||||
### Upgrade
|
||||
|
||||
Installed from the Plugins page? There is nothing to run. Press **Update** in What's new when the version number turns yellow, or use the repeater's Plugins page. Installed by hand? Run the script again:
|
||||
|
||||
```bash
|
||||
cd ~/pymc_console
|
||||
sudo bash manage.sh upgrade
|
||||
```
|
||||
|
||||
The script first brings its own checkout up to date, then replaces the dashboard files with the latest release. Your existing `web.web_path` is kept. The repeater itself is upgraded separately, with its own `manage.sh`.
|
||||
|
||||
### Uninstall
|
||||
|
||||
```bash
|
||||
cd ~/pymc_console
|
||||
sudo bash manage.sh uninstall
|
||||
```
|
||||
|
||||
This removes `/opt/pymc_console` and, after confirmation, the waev:outpost checkout, and clears `web.web_path` in the Repeater's config if it still points at the dashboard, so the Repeater falls back to its own UI. A `web_path` you set by hand to something else is left alone. It does not uninstall openHop Repeater or modify its radio setup.
|
||||
|
||||
### Automation
|
||||
|
||||
Use `--yes`/`-y` or `ASSUME_YES=1` to auto-confirm prompts:
|
||||
|
||||
```bash
|
||||
sudo bash manage.sh --yes install
|
||||
ASSUME_YES=1 sudo -E bash manage.sh upgrade
|
||||
```
|
||||
|
||||
Set `NO_COLOR=1` for plain output. Run `sudo bash manage.sh --help` for the complete command summary.
|
||||
|
||||
### Following releases
|
||||
|
||||
Release notes live in [CHANGELOG.md](CHANGELOG.md) and on the latest [GitHub release](https://github.com/Treehouse-00/pymc_console-dist/releases), and inside the console: tap the version number for **What's new**.
|
||||
|
||||
Every release is published in two places at once:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| [**waev-outpost-plugin**](https://github.com/Treehouse-00/waev-outpost-plugin) | The plugin package. This is what a repeater's Plugins page installs. |
|
||||
| [**pymc_console-dist**](https://github.com/Treehouse-00/pymc_console-dist) | This repository: the script and the files for a hand install. |
|
||||
|
||||
For bots and automation:
|
||||
|
||||
- **Atom feed** (RSS bots, Discord/Slack feed integrations):
|
||||
`https://github.com/Treehouse-00/pymc_console-dist/releases.atom`
|
||||
- **Latest release JSON** (scripts and webhooks — no auth required; `tag_name`, `body`, assets):
|
||||
`https://api.github.com/repos/Treehouse-00/pymc_console-dist/releases/latest`
|
||||
- **Raw changelog** (full history as markdown):
|
||||
`https://raw.githubusercontent.com/Treehouse-00/pymc_console-dist/main/CHANGELOG.md`
|
||||
|
||||
---
|
||||
|
||||
## Management boundaries
|
||||
|
||||
`manage.sh` is intentionally dashboard-only:
|
||||
|
||||
| Command | waev:outpost action | Repeater impact |
|
||||
|---|---|---|
|
||||
| `install` | Installs the latest dashboard into `/opt/pymc_console/web/html/` | Sets `web.web_path` on first install when possible |
|
||||
| `upgrade` | Self-updates the checkout and replaces dashboard assets | Preserves Repeater configuration and service state |
|
||||
| `uninstall` | Removes waev:outpost assets and its checkout after confirmation; clears `web.web_path` if it still points at the dashboard | Does not uninstall Repeater |
|
||||
|
||||
Use Repeater's installer or standard service tools for backend lifecycle:
|
||||
|
||||
```bash
|
||||
sudo systemctl status openhop-repeater
|
||||
sudo systemctl restart openhop-repeater
|
||||
sudo journalctl -u openhop-repeater -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Repeater compatibility
|
||||
|
||||
waev:outpost is built against the openHop Repeater `dev` branch and checked against it before each release; this release was checked against `dev` as of 2 September 2026 and against a 1.1.2 development build in daily use. Everything the console shows comes from the Repeater's own HTTP API and its two WebSocket streams, `/ws/packets` for the live mesh and `/ws/companion_frame` for the companion page; the console applies no patches to the Repeater and needs nothing installed beside it.
|
||||
|
||||
Where the Repeater renamed something, the console reads both the old and the new name and writes whichever the Repeater it is talking to understands, so an older Repeater keeps working:
|
||||
|
||||
- Modem transports: `pymc_tcp` and `pymc_usb` became `modem_tcp` and `modem_usb` in August 2026.
|
||||
- The modem sensor: `pymc_modem` became `openhop_modem`.
|
||||
- ACL roles: the Repeater now reports `admin`, `read_write`, `read_only` and `guest` with MeshCore's numbering; older ones report only `admin` and `guest`.
|
||||
- The stats WebSocket now carries the sidebar vitals (uptime, mode, utilisation, noise floor, advert tier) in every beat and the 24-hour packet aggregate one beat in six; the console reads either cadence.
|
||||
- Noise-floor history is paged: a Repeater from September 2026 answers with up to 300 samples an hour of the window where older ones answered with the newest 1,000 samples, so the console now asks for a bounded page on every Repeater.
|
||||
- Config exports and the stats view redact the modem's TCP token to `*** REDACTED ***`; posting that value back leaves the stored token in place, so a re-imported export or a saved radio form never clears it.
|
||||
- A multi-radio Repeater lists its radios and names a default; the Configuration page's Radio module and the Radio Hardware page pick which one to edit and write to that radio's entry. Packets from such a Repeater carry `rx_radio_id` and `tx_radio_id`, which are typed but not yet shown on a packet row.
|
||||
|
||||
Two optional back ends are used when present and done without otherwise. The analytics API (`/api/analytics/*`) is not part of the upstream Repeater; without it the console computes topology, disambiguation and sparklines itself. The companion REST API (`/api/v1/companions`) comes from our fork of the Repeater; without it the companion page works over the frame stream alone.
|
||||
|
||||
Features that need a Repeater from mid-2026 or newer hide themselves on an older one rather than failing: the direct advert key beside Send Advert and the direct advert interval fields, the discovered regions list and a node's region scopes with its "ask now" key, the MQTT page's neighbours-table schedule and Publish now key, the CAD page's Manual Check, the Neighbour Links page under Statistics, and the multi-radio selector. The Logs page listens to the Repeater's log stream and falls back to polling when the stream is refused.
|
||||
|
||||
Repeater features the console knows about but does not draw yet, kept in its API layer with a note of where each belongs: noise-floor and route statistics, the count of adverts by node class, the Docker-safety flag on serial ports, a BME280 sensor card, server-side session verification, the radio a packet arrived on, and the server-sent-event streams for GPS and neighbour discovery where the console still polls.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### waev:outpost does not load, or the Repeater's own UI appears
|
||||
|
||||
```bash
|
||||
sudo systemctl status openhop-repeater
|
||||
curl -s http://localhost:8000/api/stats | head -c 200
|
||||
sudo journalctl -u openhop-repeater -n 100
|
||||
```
|
||||
|
||||
Confirm that `/etc/openhop_repeater/config.yaml` contains:
|
||||
|
||||
```yaml
|
||||
web:
|
||||
web_path: /opt/pymc_console/web/html
|
||||
```
|
||||
|
||||
If `yq` was unavailable during install, the installer prints the exact command needed to set this value. Set it by hand, then restart the service:
|
||||
|
||||
```bash
|
||||
sudo yq -i '.web.web_path = "/opt/pymc_console/web/html"' /etc/openhop_repeater/config.yaml
|
||||
sudo systemctl restart openhop-repeater
|
||||
```
|
||||
|
||||
### `manage.sh install` says Repeater is not installed
|
||||
|
||||
The installer looks for `/opt/openhop_repeater` (and the older `/opt/pymc_repeater`). Install Repeater first with its own `manage.sh`, then rerun the waev:outpost installer. A Docker image of Repeater already contains waev:outpost; do not install it inside the container.
|
||||
|
||||
### Login fails or the UI and API disagree
|
||||
|
||||
Update Repeater and waev:outpost independently, then hard-refresh the browser:
|
||||
|
||||
```bash
|
||||
cd ~/openhop_repeater && sudo bash ./manage.sh upgrade
|
||||
cd ~/pymc_console && sudo bash manage.sh upgrade
|
||||
```
|
||||
|
||||
Use `Cmd+Shift+R` on macOS or `Ctrl+Shift+R` on Linux/Windows to bypass a stale cached `index.html`. The version badge in the sidebar shows the build you are running.
|
||||
|
||||
### waev:outpost loads but no packets appear
|
||||
|
||||
- Allow a fresh Repeater 30–60 seconds to initialize.
|
||||
- Confirm radio frequency, GPIO, and SPI/USB transport in Repeater configuration.
|
||||
- Check the live service log with `journalctl`.
|
||||
- The connection dot in the sidebar reports the packet WebSocket. If it degrades, the console falls back to polling; if it stays offline, check that nothing between the browser and port 8000 strips WebSocket upgrades.
|
||||
|
||||
### Channels show hashes instead of names
|
||||
|
||||
A channel is named when its hash matches the curated list or a channel you have joined. Under Messages → Manage, join a hashtag channel by name, or a private channel by pasting its key, and traffic already in the local cache is decrypted for it.
|
||||
|
||||
### The companion page says another client is connected
|
||||
|
||||
A companion's Frame link serves one client at a time. Close the other session, or take the link from this one with the TAKE key in the STATUS pocket; the other client is told it was displaced. The Companion API mode keeps chat available without the Frame link at all, at the cost of the trusted radio controls.
|
||||
|
||||
### Data looks stale, or the repeater's database has grown large
|
||||
|
||||
The console caches packets in browser storage so history survives reloads; a hard refresh rebuilds that cache from the repeater. The repeater's own database is managed under System → Storage, where tables can be purged and the file vacuumed.
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
```
|
||||
Browser
|
||||
└─ waev:outpost (React + TypeScript + Vite)
|
||||
├─ REST API: configuration, history, analytics, system state
|
||||
├─ WebSocket: live radio and packet events
|
||||
├─ Browser storage: localStorage packet cache, IndexedDB companion messages
|
||||
└─ Web workers: bucketing, decoding, and topology analysis
|
||||
│
|
||||
▼
|
||||
openHop Repeater (Python service, port 8000)
|
||||
├─ authentication and API
|
||||
├─ packet forwarding and persistence
|
||||
├─ radio and GPIO control
|
||||
└─ openHop Core / MeshCore protocol implementation
|
||||
```
|
||||
|
||||
waev:outpost is deployed as static assets under `/opt/pymc_console/web/html/`. Repeater serves the SPA and the same-origin API, which avoids a second production service or cross-origin configuration. The console applies no patches to Repeater and writes one setting in its config, `web.web_path`.
|
||||
|
||||
### Analysis pipeline
|
||||
|
||||
MeshCore paths carry two-character node prefixes, so several nodes may match a hop. waev:outpost uses a Viterbi hidden Markov model to select the most probable path from known candidates plus an unknown-node state. Scoring combines observation recency, prefix co-occurrence, path position, geographic plausibility, and measured edge evidence. The resulting topology powers path confidence, ghost-node discovery, link analysis, and TX-delay recommendations.
|
||||
|
||||
The frontend also contains a TypeScript MeshCore protocol implementation for binary frame parsing, packet-type decoding, channel-key derivation, and group-text decryption. Heavy work runs in web workers so the instruments stay responsive on a phone.
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
The source repository uses React 18, TypeScript, Vite 6, Zustand, MapLibre GL, µPlot, and xterm.js.
|
||||
|
||||
Installing source dependencies requires access to the Motion+ registry. CI injects the repository's `MOTION_TOKEN` into the `__MOTION_TOKEN__` placeholders in `package.json` and `package-lock.json`. For a fresh local install, do the same with the same organization credential: run `MOTION_TOKEN=<token> ./scripts/inject-motion-token.sh` from the repository root before `npm install`, then `./scripts/inject-motion-token.sh restore` to put the placeholders back.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Treehouse-00/pymc_console.git
|
||||
cd pymc_console/frontend
|
||||
cp .env.example .env.local
|
||||
# Set VITE_API_URL in .env.local to a running Repeater, then:
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Useful checks:
|
||||
|
||||
```bash
|
||||
npm run typecheck
|
||||
npm run test
|
||||
npm run lint
|
||||
npm run build
|
||||
```
|
||||
|
||||
Production builds are written to `frontend/out/`; `npm run build:static` also copies the packaged output to `frontend/dist/`.
|
||||
|
||||
### openHop plugin wheel
|
||||
|
||||
The console also ships as a UI-only openHop plugin. Once the wheel is installed and enabled, the repeater can select the plugin's `ui/` directory as its primary frontend (its `web.web_path`), so waev:outpost answers at the root URL exactly where the built-in dashboard or a standalone install would; `/plugins/waev.outpost/` remains as an optional direct route to the same build. Switching between the built-in dashboard, a standalone install and the plugin keeps the root URL. From `frontend/`:
|
||||
|
||||
```bash
|
||||
npm run build:plugin
|
||||
```
|
||||
|
||||
That builds the SPA a second time with the absolute `/plugins/waev.outpost/` base into `frontend/out-plugin/` (the root install keeps `/`; a relative base would break nested deep links), stages `plugin-stage/` (`openhop-plugin.json` stamped with the package version, plus `ui/`), and packs a PEP 427 wheel under `plugin-dist/`:
|
||||
|
||||
```text
|
||||
plugin-dist/waev_outpost_plugin-<version>-py3-none-any.whl
|
||||
```
|
||||
|
||||
Install the wheel from the repeater's **System → Plugins** page (or `POST /api/plugins/install`), enable it, then either select it as the repeater's frontend and open `/`, or open `/plugins/waev.outpost/` directly. Every release publishes the wheel as the single `.whl` asset of the [waev-outpost-plugin](https://github.com/Treehouse-00/waev-outpost-plugin) release. Published plugin releases are retained because approved catalogue entries and rollbacks use exact versioned release URLs. After publication, the Console catalogue workflow downloads and verifies those release bytes, calculates their SHA-256, and opens a ready PR for `waev.outpost` through the catalogue publisher GitHub App. Catalogue-owned certification policy and required checks control automatic merging; retries preserve any existing human-selected draft state. See [release setup](RELEASE.md) for the required repository secrets. Re-pack only (after a prior stage) with `npm run pack:plugin`.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT. See [LICENSE](LICENSE).
|
||||
|
||||
## Credits
|
||||
|
||||
- [RightUp](https://github.com/rightup) — creator of the original pyMC Repeater/Core projects and a maintainer of the MeshCore Python ecosystem
|
||||
- [openHop Repeater](https://github.com/openhop-dev/openhop_repeater) — Repeater daemon and the backend waev:outpost plugs into
|
||||
- [openHop Core](https://github.com/openhop-dev/openhop_core) — MeshCore protocol library
|
||||
- [MeshCore](https://meshcore.io/) — MeshCore project and community
|
||||
- [d40cht/meshcore-connectivity-analysis](https://github.com/d40cht/meshcore-connectivity-analysis) — Viterbi HMM approach for path disambiguation
|
||||
- [meshcore-bot](https://github.com/agessaman/meshcore-bot) — recency scoring and dual-hop anchor disambiguation
|
||||
|
||||
---
|
||||
|
||||
<p align="center"><sub>waev:outpost is built as hardware: every page is an instrument, not a form. Bolt it to your repeater and watch the mesh breathe.</sub></p>
|
||||
- [Complete installation, migration and recovery guide](INSTALL.md)
|
||||
- [Supported plugin repository and release notes](https://github.com/Treehouse-00/waev-outpost-plugin)
|
||||
- [Plugin releases](https://github.com/Treehouse-00/waev-outpost-plugin/releases) · [release feed](https://github.com/Treehouse-00/waev-outpost-plugin/releases.atom)
|
||||
- [Retained standalone v0.9.394 downloads](https://github.com/Treehouse-00/pymc_console-dist/releases/tag/v0.9.394)
|
||||
- [Legacy release information](RELEASE.md) · [legacy changelog](CHANGELOG.md) · [license](LICENSE)
|
||||
+18
-306
@@ -1,318 +1,30 @@
|
||||
# waev:outpost Release Guide
|
||||
# Legacy standalone releases
|
||||
|
||||
Complete guide for developers to create and publish new releases of waev:outpost.
|
||||
**The `pymc_console-dist` standalone channel is retired. Its final release is v0.9.394.** New waev:outpost releases are published as the `waev.outpost` application UI plugin in [waev-outpost-plugin](https://github.com/Treehouse-00/waev-outpost-plugin), including [v0.9.396](https://github.com/Treehouse-00/waev-outpost-plugin/releases/tag/v0.9.396).
|
||||
|
||||
## Table of Contents
|
||||
- [Quick Release Steps](#quick-release-steps)
|
||||
- [Understanding the Release Process](#understanding-the-release-process)
|
||||
- [Manual Build Process](#manual-build-process)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Version Numbering](#version-numbering)
|
||||
## Retained standalone downloads
|
||||
|
||||
---
|
||||
The [v0.9.394 release](https://github.com/Treehouse-00/pymc_console-dist/releases/tag/v0.9.394) and these existing assets remain available for legacy installations:
|
||||
|
||||
## Quick Release Steps
|
||||
| Asset | Purpose |
|
||||
|---|---|
|
||||
| [`pymc-ui-v0.9.394.tar.gz`](https://github.com/Treehouse-00/pymc_console-dist/releases/download/v0.9.394/pymc-ui-v0.9.394.tar.gz) | Final standalone tar archive |
|
||||
| [`pymc-ui-v0.9.394.zip`](https://github.com/Treehouse-00/pymc_console-dist/releases/download/v0.9.394/pymc-ui-v0.9.394.zip) | Final standalone ZIP archive |
|
||||
| [`pymc-ui-latest.tar.gz`](https://github.com/Treehouse-00/pymc_console-dist/releases/download/v0.9.394/pymc-ui-latest.tar.gz) | Existing installer-compatible name for the same final tar archive |
|
||||
| [`pymc-ui-latest.zip`](https://github.com/Treehouse-00/pymc_console-dist/releases/download/v0.9.394/pymc-ui-latest.zip) | Existing installer-compatible name for the same final ZIP archive |
|
||||
|
||||
Run the repository-owned release command from the project root. Patch is the
|
||||
default; use `minor` or `major` only when the release explicitly requires it.
|
||||
The `latest` names do not mean the standalone channel will receive further updates. The old `manage.sh upgrade` remains a standalone operation and does not migrate an installation to the plugin. Historical notes remain in [CHANGELOG.md](CHANGELOG.md).
|
||||
|
||||
```bash
|
||||
./release.sh "feat: concise release subject"
|
||||
```
|
||||
## Install and update the supported plugin
|
||||
|
||||
Write the full operator-facing notes in `CHANGELOG.md` first. The script
|
||||
fetches `origin/main` and aborts before touching anything if that ref is not an
|
||||
ancestor of `HEAD` (Step 0), runs the public distribution gates and refuses to
|
||||
release if they fail (Step 0.5), validates source, commits source without generated
|
||||
`dist/`, bumps the version, inserts a one-line `CHANGELOG.md` stanza only when
|
||||
the new version has none (Step 3.5), rebuilds the bundle with that final
|
||||
version, commits `dist/` with the version files, then tags and pushes `HEAD` to
|
||||
`origin/main`. Only `patch`, `minor`, and `major` are accepted.
|
||||
Start with the [migration steps in README.md](README.md#move-to-the-plugin) or the [complete installation guide](INSTALL.md#migrate-from-the-standalone-install). Keep your old folder, Repeater configuration and credentials while verifying the plugin.
|
||||
|
||||
---
|
||||
In the legacy console, **Configuration → Web Frontend → Default Frontend** returns to the built-in Repeater interface immediately. From there, **System → Plugins → Catalogue → waev:outpost → Install** installs and enables the approved plugin. Confirm **UI READY**, use **Enable** if disabled, and open `/plugins/waev.outpost/`. Make it the default under **System → Configuration → Access → Web Options → Web Frontend**, selecting the plugin entry.
|
||||
|
||||
## Understanding the Release Process
|
||||
For a specific published version, download its `.whl` from [plugin releases](https://github.com/Treehouse-00/waev-outpost-plugin/releases) and use **System → Plugins → Install wheel**. Enable it if needed and test its direct URL before changing the default.
|
||||
|
||||
### What Happens Automatically
|
||||
Catalogue installs receive approved updates through **Plugins → Catalogue → Refresh → Update**, or the available plugin update in waev:outpost's **What's new** dialog. Fresh local-wheel installs may lack update tracking; upload a newer wheel again or adopt catalogue installation using the [documented API](INSTALL.md#automation). A release is available in the catalogue only after approval, which may follow GitHub publication.
|
||||
|
||||
This project uses **GitHub Actions** for continuous integration and deployment:
|
||||
Published plugin versions and their versioned wheel downloads are retained. Follow the [plugin release feed](https://github.com/Treehouse-00/waev-outpost-plugin/releases.atom) for new releases. This repository's retained standalone assets are a fallback, not the current update channel.
|
||||
|
||||
#### In the Private Source Repository:
|
||||
- In the private source repository, `build-ui.yml` verifies and uploads the
|
||||
committed `frontend/dist/` package and tests the distribution workflow.
|
||||
- In the public distribution repository, `build-ui.yml` validates the installer
|
||||
and rejects tracked `frontend/dist/` files; it does not upload a UI artifact.
|
||||
- A normal branch push does not change the public distribution repository.
|
||||
|
||||
#### On Version Tag Push (for example `v0.9.356`):
|
||||
- `sync-to-public.yml` rebuilds the UI outside Git and writes installer files,
|
||||
version metadata, and documentation to a new parentless commit.
|
||||
- It runs once per public repository, in parallel (a job matrix): the console
|
||||
target publishes the UI archives to `Treehouse-00/pymc_console-dist`, and the
|
||||
plugin target builds the openHop plugin wheel (`npm run build:plugin`) and
|
||||
publishes it as the single `.whl` asset on `Treehouse-00/waev-outpost-plugin`.
|
||||
Both repositories receive the same one-commit snapshot; the plugin one also
|
||||
carries `openhop-plugin.json`. `PUBLIC_REPO_TOKEN` must be able to push to both.
|
||||
- `./release.sh "…" --targets=plugin` (or `--targets=console`) narrows a
|
||||
release to one repository. The flag is written to the `PUBLISH_TARGETS`
|
||||
repository variable before the tag is pushed, and rewritten to the default
|
||||
`console,plugin` on every run without the flag, so a narrowed release never
|
||||
carries into the next one. The other repository keeps its previous release.
|
||||
- The console distribution remains latest-only: public `main` is replaced and
|
||||
older console tags/releases are deleted after the new release is live.
|
||||
- Plugin releases are immutable and retained. Exact versioned wheel URLs in the
|
||||
catalogue must remain downloadable for approved installs and rollbacks.
|
||||
- After a successful public sync, `propose-plugin-catalogue.yml` downloads the
|
||||
published wheel, validates its RECORD and embedded metadata, hashes those exact
|
||||
bytes, and opens a version-specific ready PR against
|
||||
`openhop-dev/openhop-plugin-catalogue`. The catalogue-owned certification policy
|
||||
and required checks control automatic merging; the producer does not enable
|
||||
auto-merge or declare certification. Retries update the existing PR's evidence
|
||||
without changing a human-selected draft/ready state.
|
||||
- Configure the `openhop-catalogue-publisher` GitHub App (ID `4844131`): install it
|
||||
on `openhop-dev/openhop-plugin-catalogue` with Contents read/write, Pull requests
|
||||
read/write, and Metadata read-only. In the producer source repository
|
||||
(`Treehouse-00/pymc_console`), store `OPENHOP_CATALOGUE_APP_ID` (value `4844131`)
|
||||
and `OPENHOP_CATALOGUE_APP_PRIVATE_KEY` (the App PEM private key) as **both required repository secrets**,
|
||||
not repository variables. Never print the private key. Keep artifact publication's
|
||||
`PUBLIC_REPO_TOKEN` separate; it is not a catalogue credential.
|
||||
- Public catalogue checkout uses the read-only `github.token` without persisted
|
||||
credentials. Only after release-byte verification and the catalogue validator
|
||||
pass does the SHA-pinned `actions/create-github-app-token` v2.2.2 mint a
|
||||
short-lived installation token, restricted to that catalogue and those permissions.
|
||||
The action revokes it at job completion. The publish step uses the installation
|
||||
token for bot-authored PRs and resolves `openhop-catalogue-publisher[bot]` via the
|
||||
public users API for its numeric ID and bot noreply commit address; no personal
|
||||
`/user` endpoint or PAT is used.
|
||||
- The hard postcondition requires one root commit, one `main` branch, the current
|
||||
tag/latest release, and no tracked `frontend/dist/` tree. The plugin target may
|
||||
also retain older tags and releases.
|
||||
|
||||
Generated UI files belong in release assets, not the public repository's Git
|
||||
history. The sync builds a fresh one-commit repository, keeps staged UI and
|
||||
archives outside that checkout, and scans both metadata and staged UI for secrets
|
||||
before publishing. Documentation is internal by default: only `docs/images`
|
||||
crosses over, by allowlist, and the sync aborts before pushing if anything else
|
||||
under `docs/` reached the staged tree. End-user clone examples retain `--depth 1
|
||||
--single-branch --branch main --no-tags` as a defense-in-depth bound.
|
||||
|
||||
Do **not** enable GitHub's repository-level immutable-release setting on the
|
||||
console distribution repository; its latest-only policy intentionally replaces
|
||||
the current release. The plugin release workflow rejects reuse of an existing
|
||||
published release and retains all published versions. If a failed publication
|
||||
left only an orphan tag with no release, the next run removes that unusable tag
|
||||
and retries the same version safely.
|
||||
|
||||
The private source repository's committed build and local release process are
|
||||
unchanged. For branch-only UI builds, use the private manual artifact workflow.
|
||||
|
||||
Run the distribution regression checks locally with:
|
||||
|
||||
```bash
|
||||
node --test scripts/public-distribution.test.mjs
|
||||
```
|
||||
|
||||
`release.sh` runs that same command at Step 0.5, before anything is committed or
|
||||
tagged, and aborts the release when it fails. The tag push starts the public
|
||||
sync, and that workflow does not wait for Build Validation, so a gate that only
|
||||
runs in CI would be advisory at release time.
|
||||
|
||||
### The Workflow File
|
||||
|
||||
The relevant workflows are `.github/workflows/build-ui.yml`,
|
||||
`.github/workflows/build-ui-artifact.yml`,
|
||||
`.github/workflows/sync-to-public.yml`, and
|
||||
`.github/workflows/propose-plugin-catalogue.yml`.
|
||||
|
||||
The catalogue proposal workflow can be retried without rebuilding or replacing a
|
||||
release: run **Propose waev:outpost catalogue update** manually and enter its existing
|
||||
`vMAJOR.MINOR.PATCH` tag. If that tag has no waev:outpost wheel release, the workflow
|
||||
exits successfully without creating a catalogue branch or PR.
|
||||
|
||||
---
|
||||
|
||||
## Detailed Release Steps
|
||||
|
||||
1. Finish and review the source changes on a branch based on `origin/main`.
|
||||
2. Add a dated section for the next version to `CHANGELOG.md`. Write it by
|
||||
hand: if the script finds no `## [X.Y.Z]` heading for the new version, its
|
||||
Step 3.5 inserts a placeholder stanza (dated today, sectioned by the commit
|
||||
type, one bullet from the commit subject) so the in-app "What's new" reader
|
||||
never falls behind. That stanza is a fallback, not release notes.
|
||||
3. Run the required tests, typecheck, and production build proof.
|
||||
4. Run `./release.sh "type: concise subject" [patch|minor|major]`. Its Step 0
|
||||
preflight fetches `origin/main` and aborts, before any commit or tag exists,
|
||||
when `origin/main` is not an ancestor of `HEAD` (see Troubleshooting).
|
||||
5. Verify the new tag and `origin/main`, then monitor both build and public-sync
|
||||
workflows. Confirm the published archive and release notes match the tag.
|
||||
|
||||
Do not run `npm version` and push tags by hand unless `release.sh` is
|
||||
unavailable. The script's ordering is what prevents the final JavaScript bundle
|
||||
from embedding the previous version number.
|
||||
|
||||
---
|
||||
|
||||
## Manual Build Process
|
||||
|
||||
If you need to build locally without creating a release:
|
||||
|
||||
```bash
|
||||
cd pymc_console/frontend
|
||||
|
||||
# Install dependencies (first time only). The Motion+ token must be injected
|
||||
# into the __MOTION_TOKEN__ placeholders first — see README.md, "Development".
|
||||
npm install
|
||||
|
||||
# Build static files
|
||||
npm run build:static
|
||||
```
|
||||
|
||||
The output will be in `frontend/dist/` directory.
|
||||
|
||||
### What the Build Does
|
||||
|
||||
1. `vite build` - Compiles React app to static HTML/CSS/JS
|
||||
2. Outputs to `frontend/out/`
|
||||
3. `scripts/precompress-assets.mjs` writes `.br` and `.gz` sidecars beside the
|
||||
compressible files in `out/`
|
||||
4. `npm run package` copies `out/` contents to `frontend/dist/`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Release job was skipped"
|
||||
|
||||
**Problem:** You pushed code but no GitHub Release was created.
|
||||
|
||||
**Solution:** Public release publishing only runs for version tags. Confirm that
|
||||
`release.sh` completed, that its `vX.Y.Z` tag exists on origin, and that the
|
||||
matching `sync-to-public.yml` run was not cancelled or superseded.
|
||||
|
||||
### "origin/main has moved ahead of this branch"
|
||||
|
||||
**Problem:** `release.sh` stopped at Step 0 because `origin/main` contains
|
||||
commits that `HEAD` does not.
|
||||
|
||||
**Solution:** Nothing was committed, tagged, or pushed. Run
|
||||
`git fetch origin main && git rebase origin/main`, resolve any conflicts, and
|
||||
rerun the same release command.
|
||||
|
||||
### "Build failed: npm ERR! code ELIFECYCLE"
|
||||
|
||||
**Problem:** The build process failed.
|
||||
|
||||
**Solution:**
|
||||
1. Pull the latest code: `git pull origin main`
|
||||
2. Clean install locally: `cd frontend && rm -rf node_modules && npm install` (keep
|
||||
`package-lock.json` — it is tracked, and it carries the tokenised `motion-plus`
|
||||
resolution)
|
||||
3. Test build locally: `npm run build:static`
|
||||
4. Fix any errors before pushing
|
||||
|
||||
### "Tag already exists"
|
||||
|
||||
**Problem:** You tried to create a tag that already exists.
|
||||
|
||||
**Solution:** Stop and inspect the existing local tag, remote tag, and release.
|
||||
Do not rewrite a published tag. If the tag is only local and no release was
|
||||
published, remove that local tag after confirming its exact target, then rerun
|
||||
the canonical release command with the intended version.
|
||||
|
||||
### "Permission denied" when creating release
|
||||
|
||||
**Problem:** GitHub Actions doesn't have permission to create releases.
|
||||
|
||||
**Solution:** Releases are created on the distribution repository with the
|
||||
`PUBLIC_REPO_TOKEN` PAT, not with the run's `GITHUB_TOKEN`, so the source
|
||||
repository's "Workflow permissions" setting does not govern them. Check that the
|
||||
`PUBLIC_REPO_TOKEN` secret on the `.console.env` environment still exists, has
|
||||
not expired, and still carries `repo` scope on the distribution repository.
|
||||
|
||||
---
|
||||
|
||||
## Version Numbering
|
||||
|
||||
### Semantic Versioning Format
|
||||
|
||||
`MAJOR.MINOR.PATCH` (e.g., `0.1.2`)
|
||||
|
||||
### When to Increment Each Part
|
||||
|
||||
| Change Type | Example | Command | Version Change |
|
||||
|-------------|---------|---------|----------------|
|
||||
| Bug fix | Fix broken map display | `./release.sh "fix: …" patch` | `0.1.1` → `0.1.2` |
|
||||
| New feature | Add dark mode | `./release.sh "feat: …" minor` | `0.1.2` → `0.2.0` |
|
||||
| Breaking change | Require new API version | `./release.sh "feat: …" major` | `0.2.0` → `1.0.0` |
|
||||
|
||||
### Pre-releases
|
||||
|
||||
Not supported. `release.sh` rejects any bump type other than `patch`, `minor`,
|
||||
or `major`, and `sync-to-public.yml` has no pre-release path: every tag push
|
||||
replaces the single public release.
|
||||
|
||||
---
|
||||
|
||||
## End User Deployment
|
||||
|
||||
Once a release is published, end users can deploy it. Only the latest release
|
||||
exists on the distribution repository (the sync workflow deletes every older
|
||||
release and tag), so there is no versioned download to pin.
|
||||
|
||||
### Download and Extract
|
||||
|
||||
```bash
|
||||
# Download the latest release
|
||||
wget https://github.com/Treehouse-00/pymc_console-dist/releases/latest/download/pymc-ui-latest.tar.gz
|
||||
|
||||
# Extract to the waev:outpost install target
|
||||
sudo mkdir -p /opt/pymc_console/web/html
|
||||
sudo tar -xzf pymc-ui-latest.tar.gz -C /opt/pymc_console/web/html/
|
||||
|
||||
# Or use zip (pymc-ui-latest.zip is published alongside the tarball)
|
||||
sudo unzip pymc-ui-latest.zip -d /opt/pymc_console/web/html/
|
||||
```
|
||||
|
||||
### Configure Backend
|
||||
|
||||
openHop Repeater serves these static files when `web.web_path` in
|
||||
`/etc/openhop_repeater/config.yaml` points at `/opt/pymc_console/web/html`.
|
||||
`manage.sh install` sets it on a fresh install; INSTALL.md covers the manual
|
||||
steps.
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Commands
|
||||
|
||||
```bash
|
||||
# View current version
|
||||
cat frontend/package.json | grep version
|
||||
|
||||
# List all tags
|
||||
git tag --list
|
||||
|
||||
# View latest tag
|
||||
git describe --tags --abbrev=0
|
||||
|
||||
# Delete local tag
|
||||
git tag -d v0.1.2
|
||||
|
||||
# Delete remote tag
|
||||
git push origin :refs/tags/v0.1.2
|
||||
|
||||
# Create tag manually (if npm version didn't work)
|
||||
git tag v0.1.2
|
||||
git push origin v0.1.2
|
||||
|
||||
# Check GitHub Actions status
|
||||
# Visit: https://github.com/Treehouse-00/pymc_console/actions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check GitHub Actions logs for detailed error messages
|
||||
- Review commit messages to ensure they follow conventions
|
||||
- Test builds locally before pushing tags
|
||||
- Ask in the project's discussion forum or issues section
|
||||
See [Recovery](INSTALL.md#recovery) to restore the built-in default if the current UI is unavailable. No standalone uninstall or credential reset is required to migrate.
|
||||
Reference in new issue
Block a user