chore: release version 4.8.1 with bug fixes and improvements for Windows desktop and packaging

This commit is contained in:
Ivan 2026-07-25 15:51:04 -05:00
parent 23a5d03db9
commit b0d47b9ece
No known key found for this signature in database
34 changed files with 259 additions and 33 deletions

View file

@ -13,8 +13,8 @@ body:
id: version
attributes:
label: MeshChatX version
description: The version shown in Settings or the release you installed (for example 4.8.0).
placeholder: "4.8.0"
description: The version shown in Settings or the release you installed (for example 4.8.1).
placeholder: "4.8.1"
validations:
required: true

View file

@ -14,7 +14,7 @@ body:
attributes:
label: MeshChatX version
description: The version you are using today, if relevant.
placeholder: "4.8.0"
placeholder: "4.8.1"
- type: dropdown
id: os

View file

@ -215,6 +215,9 @@ jobs:
- name: Verify FS sandbox modules bundled in frozen backend
run: bash scripts/ci/github-verify-frozen-sandbox.sh build/exe
- name: Verify frozen backend import runtime
run: bash scripts/ci/github-verify-frozen-runtime.sh build/exe
- name: Verify frozen backend has no package bloat
run: bash scripts/ci/verify-package-contents.sh frozen build/exe
@ -259,6 +262,8 @@ jobs:
.artifacts/linux-build-check/build/exe
bash scripts/ci/github-verify-frozen-sandbox.sh \
.artifacts/linux-build-check/build/exe
bash scripts/ci/github-verify-frozen-runtime.sh \
.artifacts/linux-build-check/build/exe
bash scripts/ci/verify-package-contents.sh frozen \
.artifacts/linux-build-check/build/exe
echo "Linux build artifact download + content validation passed."

View file

@ -2,6 +2,13 @@
All notable changes to this project will be documented in this file.
## [4.8.1] - 2026-07-25
### Fixed
- **Windows desktop**: Frozen backends start again instead of failing when aiohttp imports the standard library email package.
- **Desktop packaging**: Only the correct LXST filterlib binary ships per platform so integrity checks match the installer. CI runs a frozen import smoke test before release.
## [4.8.0] - 2026-07-25
### Added

View file

@ -441,7 +441,7 @@ task build
## Versioning
Current version in this repo is `4.8.0`.
Current version in this repo is `4.8.1`.
- **`package.json`** `version` is the only value you edit for a release bump.
- Run **`pnpm run version:sync`** (also run at the start of **`pnpm run build`**) to propagate that version into **`pyproject.toml`**, **`meshchatx/src/version.py`**, **`THIRD_PARTY_NOTICES.txt`** (product line), **README** / **lang/README.\*** “current version” lines, **`docs/meshchatx_on_raspberry_pi.md`** pipx example, and **`packaging/arch/PKGBUILD`** helpers.

View file

@ -50,8 +50,8 @@ android {
applicationId "com.meshchatx"
minSdk 24
targetSdk 35
versionCode 48000
versionName "4.8.0"
versionCode 48001
versionName "4.8.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {

View file

@ -68,6 +68,9 @@ packages = [
"cffi",
"ply",
"bleak",
# aiohttp pulls stdlib email at runtime. Keep the full tree out of library.zip
# so relative imports like email._policybase -> email.header work on Windows.
"email",
]
# Keep FS sandbox helpers even when import tracing is incomplete (Windows
@ -77,6 +80,7 @@ includes = [
"meshchatx.src.backend.appcontainer_sandbox",
"meshchatx.src.backend.appcontainer_launcher",
"meshchatx.src.backend.seccomp_sandbox",
"meshchatx.src.backend.frozen_freeze_probe",
]
if sys.version_info >= (3, 13):
@ -110,6 +114,7 @@ setup(
"distutils",
"pkg_resources",
],
"zip_exclude_packages": ["email"],
"optimize": 2,
"build_exe": build_exe_dir,
"replace_paths": [

View file

@ -61,17 +61,17 @@ source ~/.profile
## 3) Install MeshChatX with pipx (recommended)
Preferred option (recommended): install from a release wheel (4.8.0 or newer),
Preferred option (recommended): install from a release wheel (4.8.1 or newer),
because the wheel bundles frontend assets.
```bash
pipx install /path/to/reticulum_meshchatx-<version>-py3-none-any.whl
```
Direct example (v4.8.0):
Direct example (v4.8.1):
```bash
pipx install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.0/reticulum_meshchatx-4.8.0-py3-none-any.whl"
pipx install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.1/reticulum_meshchatx-4.8.1-py3-none-any.whl"
```
`py3-none-any` wheels are architecture-independent, so the same wheel artifact
@ -93,7 +93,7 @@ cd ~/meshchatx
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.0/reticulum_meshchatx-4.8.0-py3-none-any.whl"
python -m pip install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.1/reticulum_meshchatx-4.8.1-py3-none-any.whl"
```
Run command in venv mode:

View file

@ -352,7 +352,7 @@ task build
## Versionierung
Aktuelle Version in diesem Repository: `4.8.0`.
Aktuelle Version in diesem Repository: `4.8.1`.
- Fuer Release-Bumps bearbeiten Sie **nur** `version` in **`package.json`**.
- **`pnpm run version:sync`** (wird auch zu Beginn von **`pnpm run build`** ausgefuehrt) verbreitet diese Version in **`pyproject.toml`**, **`meshchatx/src/version.py`**, **`THIRD_PARTY_NOTICES.txt`** (Produktzeile), **README** / **lang/README.\*** (Zeilen mit aktueller Version), **`docs/meshchatx_on_raspberry_pi.md`** (pipx-Beispiel) und Hilfsfelder in **`packaging/arch/PKGBUILD`**.

View file

@ -352,7 +352,7 @@ I target `Makefile` sono wrapper sottili che delegano a `task` (stessi comandi d
## Versionamento
Versione attuale nel repository: `4.8.0`.
Versione attuale nel repository: `4.8.1`.
- L'unico valore che modifichi per un bump di release e **`version` in `package.json`**.
- Esegui **`pnpm run version:sync`** (all'inizio anche di **`pnpm run build`**) per propagare in **`pyproject.toml`**, **`meshchatx/src/version.py`**, **`THIRD_PARTY_NOTICES.txt`** (riga prodotto), **README** / **lang/README.\*** (righe "versione attuale"), **esempio pipx in `docs/meshchatx_on_raspberry_pi.md`**, e aiuti in **`packaging/arch/PKGBUILD`**.

View file

@ -352,7 +352,7 @@ task build
## バージョン管理
このリポジトリの現在のバージョンは `4.8.0` です。
このリポジトリの現在のバージョンは `4.8.1` です。
- リリースのバージョン上げは **`package.json``version` のみ**編集します。
- **`pnpm run version:sync`****`pnpm run build`** 開始時にも実行)で、**`pyproject.toml`**、**`meshchatx/src/version.py`**、**`THIRD_PARTY_NOTICES.txt`**(製品行)、**README** / **lang/README.\***(現在のバージョン行)、**`docs/meshchatx_on_raspberry_pi.md`** の pipx 例、**`packaging/arch/PKGBUILD`** の補助フィールドに反映します。

View file

@ -352,7 +352,7 @@ task build
## Версионирование
Текущая версия в репозитории: `4.8.0`.
Текущая версия в репозитории: `4.8.1`.
- Редактируйте для релизного бампа **только** поле `version` в **`package.json`**.
- Команда **`pnpm run version:sync`** (также в начале **`pnpm run build`**) распространяет эту версию в **`pyproject.toml`**, **`meshchatx/src/version.py`**, **`THIRD_PARTY_NOTICES.txt`** (строка продукта), **README** / **lang/README.\*** (строки «текущая версия»), **`docs/meshchatx_on_raspberry_pi.md`** (пример pipx) и вспомогательные поля **`packaging/arch/PKGBUILD`**.

View file

@ -352,7 +352,7 @@ task build
## 版本管理
本仓库当前版本: `4.8.0`。
本仓库当前版本: `4.8.1`。
- 发布版本号**只**改 **`package.json``version`**。
- 运行 **`pnpm run version:sync`**(在 **`pnpm run build`** 开头也会执行)可将该版本同步到 **`pyproject.toml`**、**`meshchatx/src/version.py`**、**`THIRD_PARTY_NOTICES.txt`**(产品行)、**README** / **lang/README.\*** 中的“当前版本”行、**`docs/meshchatx_on_raspberry_pi.md`** 的 pipx 示例,以及 **`packaging/arch/PKGBUILD`** 的辅助字段。

Binary file not shown.

View file

@ -3,8 +3,7 @@
"""Reticulum MeshChatX - A mesh network communications app."""
# Synced from package.json via scripts/sync_version.js (also writes meshchatx/src/version.py).
__version__ = "4.8.0"
__version__ = "4.8.1"
# LXST vendored pyogg can NameError on import when libopus is present but
# libogg is not. Apply before any meshchatx module imports LXST.
try:

View file

@ -0,0 +1,57 @@
# SPDX-License-Identifier: 0BSD
"""Prune alien LXST filterlib blobs after cx_Freeze."""
from __future__ import annotations
import sys
import sysconfig
from pathlib import Path
def _should_keep_filterlib(name: str, ext_suffix: str) -> bool:
if sys.platform == "win32" and name == "filterlib.dll":
return True
if ext_suffix and name == f"filterlib{ext_suffix}":
return True
return False
def bake_lxst_filterlib(build_dir: Path) -> None:
lxst = build_dir / "lib" / "LXST"
if not lxst.is_dir():
raise SystemExit(f"bake_frozen_lxst_native: missing {lxst}")
ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") or ""
removed = 0
kept: list[str] = []
for path in sorted(lxst.glob("filterlib*")):
if not path.is_file():
continue
if _should_keep_filterlib(path.name, ext_suffix):
kept.append(path.name)
continue
path.unlink()
removed += 1
if not kept:
raise SystemExit(
"bake_frozen_lxst_native: no filterlib native artifact for this platform "
f"({sys.platform}, EXT_SUFFIX={ext_suffix!r})"
)
print(
f"bake_frozen_lxst_native: OK kept {kept!r} (removed {removed} alien blob(s))"
)
def main() -> None:
if len(sys.argv) != 2:
raise SystemExit(
"usage: python -m meshchatx.src.backend.bake_frozen_lxst_native <build dir>"
)
bake_lxst_filterlib(Path(sys.argv[1]).resolve())
if __name__ == "__main__":
main()

View file

@ -86,7 +86,7 @@ pycparser 3.0
pyserial 3.5
License: BSD
Author: Chris Liechti
reticulum-meshchatx 4.8.0
reticulum-meshchatx 4.8.1
License: 0BSD AND MIT
Author: Quad4
rns 1.4.1

View file

@ -50,7 +50,7 @@
{
"name": "cbor2",
"version": "6.1.1",
"author": "Alex Gr\u00f6nholm <alex.gronholm@nextday.fi>",
"author": "Alex Grönholm <alex.gronholm@nextday.fi>",
"license": "MIT"
},
{
@ -157,7 +157,7 @@
},
{
"name": "reticulum-meshchatx",
"version": "4.8.0",
"version": "4.8.1",
"author": "Quad4",
"license": "0BSD AND MIT"
},

View file

@ -0,0 +1,52 @@
# SPDX-License-Identifier: 0BSD
"""Import probes for cx_Freeze desktop builds.
Invoked from CI and build-backend via:
ReticulumMeshChatX --meshchatx-run-module meshchatx.src.backend.frozen_freeze_probe
"""
from __future__ import annotations
import importlib.util
import sys
import sysconfig
from pathlib import Path
def _lxst_filterlib_path() -> Path | None:
spec = importlib.util.find_spec("LXST")
if spec is None or not spec.submodule_search_locations:
return None
root = Path(next(iter(spec.submodule_search_locations)))
if not root.is_dir():
return None
ext = sysconfig.get_config_var("EXT_SUFFIX") or ""
candidates: list[Path] = []
if sys.platform == "win32":
candidates.append(root / "filterlib.dll")
if ext:
candidates.append(root / f"filterlib{ext}")
for path in candidates:
if path.is_file():
return path
return None
def main() -> None:
import email.header # noqa: F401
import email.message # noqa: F401
import email.policy # noqa: F401
import aiohttp # noqa: F401
native = _lxst_filterlib_path()
if native is None:
raise SystemExit("frozen-freeze-probe: LXST filterlib native artifact missing")
print("frozen-freeze-probe ok", flush=True)
if __name__ == "__main__":
main()

View file

@ -17,6 +17,7 @@ from typing import Any
from meshchatx.src.backend import self_check_probe as _self_check_probe # noqa: F401
_CRITICAL_IMPORTS = (
"email.header",
"RNS",
"LXMF",
"lxmfy",

View file

@ -61,17 +61,17 @@ source ~/.profile
## 3) Install MeshChatX with pipx (recommended)
Preferred option (recommended): install from a release wheel (4.8.0 or newer),
Preferred option (recommended): install from a release wheel (4.8.1 or newer),
because the wheel bundles frontend assets.
```bash
pipx install /path/to/reticulum_meshchatx-<version>-py3-none-any.whl
```
Direct example (v4.8.0):
Direct example (v4.8.1):
```bash
pipx install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.0/reticulum_meshchatx-4.8.0-py3-none-any.whl"
pipx install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.1/reticulum_meshchatx-4.8.1-py3-none-any.whl"
```
`py3-none-any` wheels are architecture-independent, so the same wheel artifact
@ -93,7 +93,7 @@ cd ~/meshchatx
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.0/reticulum_meshchatx-4.8.0-py3-none-any.whl"
python -m pip install "https://github.com/Quad4-Software/MeshChatX/releases/download/v4.8.1/reticulum_meshchatx-4.8.1-py3-none-any.whl"
```
Run command in venv mode:

View file

@ -371,6 +371,7 @@ function createShellRuntime(options) {
}
// SPDX-License-Identifier: 0BSD
/* global ["/","/boot-theme.js","/manifest.json","/favicons/favicon-512x512.png"], cacheNameForBuild, createShellRuntime, SHELL_FALLBACK_URL, NAV_NETWORK_TIMEOUT_MS, UPDATE_MESSAGE_TYPE */
/**
* MeshChatX app-shell service worker bootstrap.
* Preceded at build time by inlined swCachePolicy.js + swShellRuntime.js.

View file

@ -1,6 +1,6 @@
{
"version": "1.2.0",
"wasm": "sha384-u89AYwtv9w30MHieh7YmTmorpfsR5A8bh+9wRJR1rgvqaRc2xjgxEiM5mvJAsA9V",
"wasm": "sha384-6bz7NFPqx6GPHO+/fb7VihhQ9OCCl5yucvUB+Z1weaBTIB/Le2ekjfJklRKbi8TD",
"wasmExec": "sha384-PWCs+V4BDf9yY1yjkD/p+9xNEs4iEbuvq+HezAOJiY3XL5GI6VyJXMsvnjiwNbce",
"wasmExecSource": "/usr/lib/go/lib/wasm/wasm_exec.js"
}

View file

@ -3,4 +3,4 @@
Do not edit by hand. Run: pnpm run version:sync
"""
__version__ = "4.8.0"
__version__ = "4.8.1"

View file

@ -1,6 +1,6 @@
{
"name": "reticulum-meshchatx",
"version": "4.8.0",
"version": "4.8.1",
"description": "A simple mesh network communications app powered by the Reticulum Network Stack",
"homepage": "https://github.com/Quad4-Software/MeshChatX",
"desktopName": "reticulum-meshchatx.desktop",

View file

@ -1,6 +1,6 @@
pkgbase = reticulum-meshchatx-git
pkgdesc = A simple mesh network communications app powered by the Reticulum Network Stack
pkgver = 4.8.0.r0.gebacc00
pkgver = 4.8.1.r0.gebacc00
pkgrel = 1
url = https://github.com/Quad4-Software/MeshChatX
arch = x86_64

View file

@ -1,7 +1,7 @@
# Maintainer: Ivan <ivan@quad4.io>
pkgname=reticulum-meshchatx-git
_pkgname=reticulum-meshchatx
pkgver=4.8.0.r0.gebacc00
pkgver=4.8.1.r0.gebacc00
pkgrel=1
pkgdesc="A simple mesh network communications app powered by the Reticulum Network Stack"
arch=('x86_64' 'aarch64')
@ -19,7 +19,7 @@ sha256sums=('SKIP'
pkgver() {
cd "$_pkgname"
git describe --long --tags 2>/dev/null | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' || \
printf "4.8.0.r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
printf "4.8.1.r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {

View file

@ -1,6 +1,6 @@
[project]
name = "reticulum-meshchatx"
version = "4.8.0"
version = "4.8.1"
description = "A simple mesh network communications app powered by the Reticulum Network Stack"
authors = [
{name = "Quad4"}

View file

@ -328,6 +328,25 @@ try {
if (isDarwin) {
stripPythonBytecodeArtifacts(buildDir);
}
const bakeCmdParts = pythonCmd.trim().split(/\s+/).filter(Boolean);
const bakeCmd = bakeCmdParts[0];
let bakeArgs = [
...bakeCmdParts.slice(1),
"-m",
"meshchatx.src.backend.bake_frozen_lxst_native",
buildDir,
];
let bakeSpawnCmd = bakeCmd;
if (rosettaX64) {
bakeSpawnCmd = "arch";
bakeArgs = ["-x86_64", bakeCmd, ...bakeArgs];
}
const bakeResult = spawnSync(bakeSpawnCmd, bakeArgs, {
stdio: "inherit",
shell: false,
env: env,
});
failOnSpawnResult("LXST filterlib prune", bakeResult);
if (!verifyBinaryArchitecture(buildDir, arch, targetName)) {
process.exit(1);
}

View file

@ -1,6 +1,6 @@
{
"dest": "meshchatx/public/reticulum-docs-bundled/current",
"fetched_utc": "2026-07-24T10:01:13Z",
"fetched_utc": "2026-07-25T20:12:03Z",
"html_files": 206,
"skipped_binary_files": 2,
"source_url": "https://codeload.github.com/markqvist/reticulum_website/zip/refs/heads/master"

View file

@ -29,6 +29,7 @@ bash scripts/ci/github-verify-electron-dist.sh win
# Ensure AppContainer/Landlock/Seccomp modules shipped in the frozen backend.
if [[ -d build/exe ]]; then
bash scripts/ci/github-verify-frozen-sandbox.sh build/exe
bash scripts/ci/github-verify-frozen-runtime.sh build/exe
fi
# Optional packaged smoke (manual / future CI job on a Windows runner):

View file

@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Run import probes inside the cx_Freeze binary (aiohttp/email/LXST natives).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
BUILD_EXE="${1:-${ROOT}/build/exe}"
if [[ ! -d "${BUILD_EXE}" ]]; then
echo "cx_Freeze output not found at ${BUILD_EXE}" >&2
exit 1
fi
if [[ ! -d "${BUILD_EXE}/lib" ]]; then
for sub in "${BUILD_EXE}"/*; do
if [[ -d "${sub}/lib" ]]; then
BUILD_EXE="${sub}"
break
fi
done
fi
EXE=""
for name in ReticulumMeshChatX ReticulumMeshChatX.exe; do
if [[ -x "${BUILD_EXE}/${name}" ]] || [[ -f "${BUILD_EXE}/${name}" ]]; then
EXE="${BUILD_EXE}/${name}"
break
fi
done
if [[ -z "${EXE}" ]]; then
echo "frozen runtime verify: backend executable not found under ${BUILD_EXE}" >&2
exit 1
fi
if [[ ! -d "${BUILD_EXE}/lib/email" ]]; then
echo "frozen runtime verify: lib/email missing (stdlib email must not live only in library.zip)" >&2
exit 1
fi
if [[ ! -f "${BUILD_EXE}/lib/email/header.py" ]]; then
shopt -s nullglob
headers=("${BUILD_EXE}/lib/email/header"*.pyc)
shopt -u nullglob
if [[ ${#headers[@]} -eq 0 ]]; then
echo "frozen runtime verify: email.header module missing under lib/email" >&2
exit 1
fi
fi
"${EXE}" --meshchatx-run-module meshchatx.src.backend.frozen_freeze_probe
echo "frozen runtime verify: OK (${EXE})"

View file

@ -0,0 +1,28 @@
# SPDX-License-Identifier: 0BSD
from __future__ import annotations
import sys
from pathlib import Path
import pytest
from meshchatx.src.backend.bake_frozen_lxst_native import bake_lxst_filterlib
def test_bake_lxst_filterlib_prunes_alien_blobs(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
lxst = tmp_path / "lib" / "LXST"
lxst.mkdir(parents=True)
(lxst / "filterlib.dll").write_bytes(b"win")
(lxst / "filterlib.cpython-314-x86_64-linux-gnu.so").write_bytes(b"linux")
monkeypatch.setattr(sys, "platform", "win32", raising=False)
monkeypatch.setattr(
"meshchatx.src.backend.bake_frozen_lxst_native.sysconfig.get_config_var",
lambda name: ".cp314-win_amd64.pyd" if name == "EXT_SUFFIX" else None,
)
bake_lxst_filterlib(tmp_path)
assert (lxst / "filterlib.dll").is_file()
assert not (lxst / "filterlib.cpython-314-x86_64-linux-gnu.so").exists()

2
uv.lock generated
View file

@ -2000,7 +2000,7 @@ wheels = [
[[package]]
name = "reticulum-meshchatx"
version = "4.8.0"
version = "4.8.1"
source = { editable = "." }
dependencies = [
{ name = "aiohttp" },