feat: sync version placeholders in issue templates and add tests for version consistency

This commit is contained in:
Ivan 2026-08-14 15:50:37 -05:00
parent 6a57db026e
commit 61f9d8e641
No known key found for this signature in database
5 changed files with 130 additions and 3 deletions

View file

@ -70,7 +70,7 @@ body:
label: Steps to reproduce
description: Numbered steps that reliably trigger the issue.
placeholder: |
1. Open MeshChatX 4.8.0 on Windows 11
1. Open MeshChatX on Windows 11
2. Add an RNode interface with port ble://...
3. Restart the app
validations:

Binary file not shown.

View file

@ -9,6 +9,7 @@
* meshchatx/src/backend/data/licenses_backend.json (reticulum-meshchatx entry),
* android/app/build.gradle,
* electron/app-version.json,
* .github/ISSUE_TEMPLATE bug and feature version placeholders,
* pipx example, packaging/arch/PKGBUILD pkgver / printf fallback,
* then runs scripts/bake_build_meta.js (git commit / channel overlay).
*
@ -141,6 +142,15 @@ console.log(`Synced version ${version} from package.json`);
const appVersionPath = path.join(root, "electron", "app-version.json");
writeIfChanged(appVersionPath, `${JSON.stringify({ version }, null, 4)}\n`);
patchFile(".github/ISSUE_TEMPLATE/bug_report.yml", (c) => {
let x = c.replace(/placeholder: "\d+\.\d+\.\d+"/, `placeholder: "${version}"`);
x = x.replace(/\(for example \d+\.\d+\.\d+\)/, `(for example ${version})`);
return x;
});
patchFile(".github/ISSUE_TEMPLATE/feature_request.yml", (c) =>
c.replace(/placeholder: "\d+\.\d+\.\d+"/, `placeholder: "${version}"`)
);
try {
require("./bake_build_meta.js");
} catch (err) {

View file

@ -0,0 +1,104 @@
# SPDX-License-Identifier: 0BSD
"""Synced version files must match package.json after pnpm run version:sync."""
from __future__ import annotations
import json
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
def _package_version() -> str:
version = json.loads((ROOT / "package.json").read_text(encoding="utf-8"))["version"]
assert isinstance(version, str) and re.match(r"^\d+\.\d+\.\d+", version)
return version
def _text(rel: str) -> str:
return (ROOT / rel).read_text(encoding="utf-8")
def test_electron_app_version_json_matches_package():
data = json.loads(_text("electron/app-version.json"))
assert data["version"] == _package_version()
def test_python_version_strings_match_package():
version = _package_version()
expected = f'__version__ = "{version}"'
assert expected in _text("meshchatx/__init__.py")
assert expected in _text("meshchatx/src/version.py")
def test_pyproject_version_matches_package():
assert re.search(
rf'^version = "{re.escape(_package_version())}"',
_text("pyproject.toml"),
re.M,
)
def test_android_version_matches_package():
version = _package_version()
major, minor, patch = (int(part) for part in version.split(".")[:3])
version_code = major * 10000 + minor * 1000 + patch
gradle = _text("android/app/build.gradle")
assert f'versionName "{version}"' in gradle
assert f"versionCode {version_code}" in gradle
def test_readme_current_version_lines_match_package():
version = _package_version()
checks = (
("README.md", f"Current version in this repo is `{version}`."),
("lang/README.de.md", f"Aktuelle Version in diesem Repository: `{version}`."),
("lang/README.it.md", f"Versione attuale nel repository: `{version}`."),
("lang/README.ja.md", f"このリポジトリの現在のバージョンは `{version}` です。"),
("lang/README.ru.md", f"Текущая версия в репозитории: `{version}`."),
("lang/README.zh.md", f"本仓库当前版本: `{version}`。"),
)
for rel, needle in checks:
assert needle in _text(rel), rel
def test_notices_and_backend_license_match_package():
version = _package_version()
notices = _text("meshchatx/src/backend/data/THIRD_PARTY_NOTICES.txt")
assert re.search(rf"^reticulum-meshchatx {re.escape(version)}$", notices, re.M)
licenses = json.loads(_text("meshchatx/src/backend/data/licenses_backend.json"))
entry = next(item for item in licenses if item.get("name") == "reticulum-meshchatx")
assert entry["version"] == version
def test_arch_packaging_version_matches_package():
version = _package_version()
pkgbuild = _text("packaging/arch/PKGBUILD")
assert re.search(rf"^pkgver={re.escape(version)}", pkgbuild, re.M)
assert f'printf "{version}.r%s.%s"' in pkgbuild
srcinfo = _text("packaging/arch/.SRCINFO")
assert re.search(rf"^\tpkgver = {re.escape(version)}", srcinfo, re.M)
def test_issue_template_placeholders_match_package():
version = _package_version()
bug = _text(".github/ISSUE_TEMPLATE/bug_report.yml")
feature = _text(".github/ISSUE_TEMPLATE/feature_request.yml")
assert f'placeholder: "{version}"' in bug
assert f"for example {version}" in bug
assert f'placeholder: "{version}"' in feature
def test_raspberry_pi_docs_match_package():
version = _package_version()
wheel = f"reticulum_meshchatx-{version}-py3-none-any.whl"
for rel in (
"docs/en/platform-guides/raspberry-pi.md",
"meshchatx/src/frontend/public/meshchatx-docs/en/platform-guides/raspberry-pi.md",
):
text = _text(rel)
assert f"({version} or newer)" in text, rel
assert f"Direct example (v{version}):" in text, rel
assert wheel in text, rel

View file

@ -1,8 +1,21 @@
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { describe, expect, it } from "vitest";
import { readPackagedAppVersion } from "../../electron/appVersion.js";
const repoRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
function readJson(relPath) {
return JSON.parse(fs.readFileSync(path.join(repoRoot, relPath), "utf8"));
}
describe("electron/appVersion", () => {
it("reads version from electron/app-version.json", () => {
expect(readPackagedAppVersion("0.0.0")).toBe("4.8.3");
it("reads the synced package.json version from electron/app-version.json", () => {
const pkgVersion = readJson("package.json").version;
const appVersion = readJson("electron/app-version.json").version;
expect(pkgVersion).toMatch(/^\d+\.\d+\.\d+/);
expect(appVersion).toBe(pkgVersion);
expect(readPackagedAppVersion("0.0.0")).toBe(pkgVersion);
});
});