version: "3" vars: PYTHON: sh: echo "${PYTHON:-python}" NPM: sh: echo "${NPM:-pnpm}" LEGACY_ELECTRON_VERSION: sh: echo "${LEGACY_ELECTRON_VERSION:-30.0.8}" WINE_PYTHON: sh: echo "${WINE_PYTHON:-wine python}" DOCKER_COMPOSE_CMD: sh: echo "${DOCKER_COMPOSE_CMD:-docker compose}" DOCKER_COMPOSE_FILE: sh: echo "${DOCKER_COMPOSE_FILE:-docker-compose.yml}" DOCKER_IMAGE: sh: echo "${DOCKER_IMAGE:-reticulum-meshchatx:local}" DOCKER_BUILDER: sh: echo "${DOCKER_BUILDER:-meshchatx-builder}" DOCKER_PLATFORMS: sh: echo "${DOCKER_PLATFORMS:-linux/amd64}" DOCKER_BUILD_FLAGS: sh: echo "${DOCKER_BUILD_FLAGS:---load}" DOCKER_BUILD_ARGS: sh: echo "${DOCKER_BUILD_ARGS:-}" DOCKER_CONTEXT: sh: echo "${DOCKER_CONTEXT:-.}" DOCKERFILE: sh: echo "${DOCKERFILE:-Dockerfile}" DOCKER_BUILD_IMAGE: sh: echo "${DOCKER_BUILD_IMAGE:-reticulum-meshchatx-build:local}" DOCKER_BUILD_FILE: sh: echo "${DOCKER_BUILD_FILE:-Dockerfile.build}" ANDROID_DIR: sh: echo "${ANDROID_DIR:-android}" PYTHON_SRC_DIR: sh: echo "${PYTHON_SRC_DIR:-${ANDROID_DIR}/app/src/main/python}" JNI_LIBS_DIR: sh: echo "${JNI_LIBS_DIR:-${ANDROID_DIR}/app/src/main/jniLibs}" RETICULUM_RNS_SRC: sh: echo "${RETICULUM_RNS_SRC:-./misc/RNS}" RETICULUM_LXMF_SRC: sh: echo "${RETICULUM_LXMF_SRC:-./misc/LXMF}" RETICULUM_LXST_SRC: sh: echo "${RETICULUM_LXST_SRC:-./misc/LXST}" SIDEBAND_CODEC2_WHL: sh: echo "${SIDEBAND_CODEC2_WHL:-./misc/pycodec2-3.0.1-cp311-cp311-linux_aarch64.whl}" SIDEBAND_LIB_ARM64: sh: echo "${SIDEBAND_LIB_ARM64:-./misc/libcodec2-arm64-v8a.so}" SIDEBAND_LIB_ARMEABI: sh: echo "${SIDEBAND_LIB_ARMEABI:-./misc/libcodec2-armeabi-v7a.so}" tasks: default: desc: Show available tasks cmds: - task --list # --- Initialization & Dependencies --- install: desc: Install all dependencies (frontend and backend) deps: [deps:fe, deps:be] setup:wine: desc: Setup Wine environment for Windows cross-builds cmds: - ./scripts/setup_wine_env.sh deps:fe: desc: Install Node.js dependencies cmds: - "{{.NPM}} install" deps:be: desc: Install Python dependencies using Poetry cmds: - poetry install setup:be: desc: Full backend environment setup cmds: - poetry install - poetry run pip install ruff # --- Execution --- run: desc: Run the application deps: [install] cmds: - poetry run meshchat dev: desc: Run in development mode (builds frontend first) deps: [build:fe] cmds: - task: run start: desc: Run the application via Electron Forge cmds: - "{{.NPM}} run start" package: desc: Package the application with Electron Forge cmds: - "{{.NPM}} run package" make: desc: Generate distributables with Electron Forge cmds: - "{{.NPM}} run make" # --- Code Quality --- lint: desc: Run all linters deps: [lint:fe, lint:be] lint:all: desc: Run all linters deps: [lint:fe, lint:be] lint:be: desc: Lint Python code (ruff) cmds: - poetry run ruff check . - poetry run ruff format --check . lint:fe: desc: Lint frontend code cmds: - "{{.NPM}} run lint" fmt:all: desc: Format all code deps: [fmt:fe, fmt:be] fmt:be: desc: Format Python code (ruff) cmds: - poetry run ruff format ./ --exclude tests - poetry run ruff check --fix ./ --exclude tests fmt:fe: desc: Format frontend code (Prettier/ESLint) cmds: - "{{.NPM}} run format" - "{{.NPM}} run lint:fix" # --- Testing & Analysis --- test:all: desc: Run all tests deps: [test:be, test:fe, test:lang] test:be: desc: Run Python tests (pytest) cmds: - poetry run pytest tests/backend --cov=meshchatx/src/backend test:be:cov: desc: Run Python tests with detailed coverage cmds: - poetry run pytest tests/backend --cov=meshchatx/src/backend --cov-report=term-missing test:fe: desc: Run frontend tests (vitest) cmds: - "{{.NPM}} run test -- --exclude tests/frontend/i18n.test.js" test:lang: desc: Run localization tests cmds: - "{{.NPM}} run test tests/frontend/i18n.test.js" - "poetry run pytest tests/backend/test_translator_handler.py" test:integrity: desc: Run data integrity tests cmds: - poetry run pytest tests/backend/test_integrity.py tests/backend/test_backend_integrity.py test:cov: desc: Run all tests with coverage deps: [test:be:cov, test:fe] bench:be: desc: Run backend benchmarks cmds: - poetry run python tests/backend/run_comprehensive_benchmarks.py bench:be:extreme: desc: Run extreme stress benchmarks cmds: - poetry run python tests/backend/run_comprehensive_benchmarks.py --extreme profile:mem: desc: Run memory profiling cmds: - poetry run pytest tests/backend/test_memory_profiling.py check: desc: Run formatting, linting, and testing sequentially cmds: - task: fmt:all - task: lint:all - task: test:all compile: desc: Compile Python to check for syntax errors cmds: - "{{.PYTHON}} -m compileall meshchatx/" # --- Build & Packaging --- build:all: desc: Build frontend and prepare backend deps: [install] cmds: - "{{.NPM}} run build" build:fe: desc: Build frontend assets deps: [deps:fe] cmds: - "{{.NPM}} run build-frontend" build:wheel: desc: Build Python wheel package deps: [install] cmds: - poetry build -f wheel - "{{.PYTHON}} scripts/move_wheels.py" # --- Electron Distribution --- dist:linux:appimage: desc: Build Linux AppImage deps: [build:fe] cmds: - "{{.NPM}} run electron-postinstall" - "PLATFORM=linux {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage" dist:linux:arm64: desc: Build Linux arm64 AppImage deps: [build:fe] cmds: - "{{.NPM}} run electron-postinstall" - "PLATFORM=linux ARCH=arm64 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage --arm64" dist:win:exe: desc: Build Windows portable EXE deps: [build:fe] cmds: - "{{.NPM}} run electron-postinstall" - "PLATFORM=win32 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --win portable" dist:win:arm64: desc: Build Windows arm64 portable EXE deps: [build:fe] cmds: - "{{.NPM}} run electron-postinstall" - "PLATFORM=win32 ARCH=arm64 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --win portable --arm64" dist:win:wine: desc: Build Windows EXE/Installer via Wine deps: [build:fe] cmds: - "{{.NPM}} run electron-postinstall" - "PLATFORM=win32 PYTHON_CMD='{{.WINE_PYTHON}}' {{.NPM}} run build-backend" - "npx electron-builder --win portable nsis --publish=never" dist:fe:linux: desc: Build Linux Electron app (prebuilt backend) deps: [build:fe] cmds: - "{{.NPM}} run dist:linux" dist:fe:rpm: desc: Build RPM package deps: [build:fe] cmds: - "{{.NPM}} run dist:rpm" dist:fe:flatpak: desc: Build Flatpak package deps: [build:fe] cmds: - "{{.NPM}} run dist:flatpak" dist:fe:win: desc: Build Windows Electron apps deps: [build:fe] cmds: - "{{.NPM}} run dist:windows" dist:fe:zip: desc: Build Electron ZIP (Forge) deps: [build:fe] cmds: - "PLATFORM=linux {{.NPM}} run build-backend" - "{{.NPM}} run dist:zip" dist:all: desc: Build all Electron apps (Linux + Win) deps: [build:fe] cmds: - "{{.NPM}} run electron-postinstall" - "PLATFORM=linux {{.NPM}} run build-backend" - "PLATFORM=win32 {{.NPM}} run build-backend" - "{{.NPM}} run dist -- --linux AppImage deb --win portable nsis" dist:all:wine: desc: Build all Electron apps (Linux + Win via Wine) deps: [build:fe] cmds: - "{{.NPM}} run electron-postinstall" - "PLATFORM=linux {{.NPM}} run build-backend" - "PLATFORM=win32 PYTHON_CMD='{{.WINE_PYTHON}}' {{.NPM}} run build-backend" - "npx electron-builder --linux AppImage deb --win portable nsis --publish=never" # --- Legacy Electron Builds --- dist:legacy:linux: desc: Build Linux AppImage (Legacy Electron) deps: [build:fe] cmds: - "PLATFORM=linux {{.NPM}} run build-backend" - "npx electron-builder -c package-legacy.json --linux AppImage --publish=never" dist:legacy:win: desc: Build Windows EXE (Legacy Electron) deps: [build:fe] cmds: - "PLATFORM=win32 {{.NPM}} run build-backend" - "npx electron-builder -c package-legacy.json --win portable --publish=never" dist:legacy:win:wine: desc: Build Windows EXE via Wine (Legacy Electron) deps: [build:fe] cmds: - "PLATFORM=win32 PYTHON_CMD='{{.WINE_PYTHON}}' {{.NPM}} run build-backend" - "npx electron-builder -c package-legacy.json --win portable nsis --publish=never" dist:legacy:all: desc: Build all Legacy apps deps: [build:fe] cmds: - "PLATFORM=linux {{.NPM}} run build-backend" - "PLATFORM=win32 {{.NPM}} run build-backend" - "npx electron-builder -c package-legacy.json --linux AppImage deb --win portable nsis --publish=never" # --- Docker --- docker:build: desc: Build Docker image (buildx) cmds: - | if ! docker buildx inspect {{.DOCKER_BUILDER}} >/dev/null 2>&1; then docker buildx create --name {{.DOCKER_BUILDER}} --use >/dev/null else docker buildx use {{.DOCKER_BUILDER}} fi - | docker buildx build --builder {{.DOCKER_BUILDER}} --platform {{.DOCKER_PLATFORMS}} \ {{.DOCKER_BUILD_FLAGS}} \ -t {{.DOCKER_IMAGE}} \ {{.DOCKER_BUILD_ARGS}} \ -f {{.DOCKERFILE}} \ {{.DOCKER_CONTEXT}} docker:run: desc: Run Docker container (compose) cmds: - 'MESHCHAT_IMAGE="{{.DOCKER_IMAGE}}" {{.DOCKER_COMPOSE_CMD}} -f {{.DOCKER_COMPOSE_FILE}} up --remove-orphans --pull never reticulum-meshchatx' docker:run:dev: desc: Run Docker container (dev compose) cmds: - 'MESHCHAT_IMAGE="{{.DOCKER_IMAGE}}" {{.DOCKER_COMPOSE_CMD}} -f docker-compose.dev.yml up --build --remove-orphans reticulum-meshchatx' docker:build:env: desc: Build containerized build environment cmds: - docker build -t {{.DOCKER_BUILD_IMAGE}} -f {{.DOCKER_BUILD_FILE}} . docker:build:artifacts: desc: Build and export artifacts from container cmds: - docker rm -f meshchat-build-temp || true - docker run --name meshchat-build-temp {{.DOCKER_BUILD_IMAGE}} - mkdir -p dist python-dist - docker cp meshchat-build-temp:/app/dist/. ./dist/ - docker cp meshchat-build-temp:/app/python-dist/. ./python-dist/ - docker rm meshchat-build-temp # --- Android --- android:init: desc: Initialize Gradle wrapper cmds: - | if [ ! -f "{{.ANDROID_DIR}}/gradle/wrapper/gradle-wrapper.jar" ]; then echo "Downloading Gradle wrapper jar..." mkdir -p "{{.ANDROID_DIR}}/gradle/wrapper" curl -L -o "{{.ANDROID_DIR}}/gradle/wrapper/gradle-wrapper.jar" \ https://raw.githubusercontent.com/gradle/gradle/v8.12.1/gradle/wrapper/gradle-wrapper.jar || \ echo "Failed to download. Please run: cd {{.ANDROID_DIR}} && gradle wrapper --gradle-version 8.12.1" else echo "Gradle wrapper already initialized." fi android:prepare: desc: Prepare Android source assets deps: [build:fe, android:init] cmds: - | echo "Copying meshchatx package and dependencies to Android project..." mkdir -p "{{.PYTHON_SRC_DIR}}" rm -rf "{{.PYTHON_SRC_DIR}}/meshchatx" rm -rf "{{.PYTHON_SRC_DIR}}/RNS" rm -rf "{{.PYTHON_SRC_DIR}}/LXMF" rm -rf "{{.PYTHON_SRC_DIR}}/LXST" cp -r meshchatx "{{.PYTHON_SRC_DIR}}/" cp -r ./misc/RNS "{{.PYTHON_SRC_DIR}}/" cp -r ./misc/LXMF "{{.PYTHON_SRC_DIR}}/" cp -r ./misc/LXST "{{.PYTHON_SRC_DIR}}/" cp -r ./src/RNS "{{.PYTHON_SRC_DIR}}/" || true cp -r ./src/LXMF "{{.PYTHON_SRC_DIR}}/" || true cp -r ./src/LXST "{{.PYTHON_SRC_DIR}}/" || true cp "./misc/pycodec2-3.0.1-cp311-cp311-linux_aarch64.whl" "{{.PYTHON_SRC_DIR}}/" || true mkdir -p "{{.JNI_LIBS_DIR}}/arm64-v8a" mkdir -p "{{.JNI_LIBS_DIR}}/armeabi-v7a" cp "./misc/libcodec2-arm64-v8a.so" "{{.JNI_LIBS_DIR}}/arm64-v8a/" || true cp "./misc/libcodec2-armeabi-v7a.so" "{{.JNI_LIBS_DIR}}/armeabi-v7a/" || true rm -rf "{{.PYTHON_SRC_DIR}}/RNS/Utilities/RNS" rm -rf "{{.PYTHON_SRC_DIR}}/LXMF/Utilities/LXMF" rm -rf "{{.PYTHON_SRC_DIR}}/LXST/Utilities/LXST" android:build: desc: Build Debug APK deps: [android:prepare] cmds: - cd "{{.ANDROID_DIR}}" && ./gradlew assembleDebug android:build:release: desc: Build Release APK deps: [android:prepare] cmds: - cd "{{.ANDROID_DIR}}" && ./gradlew assembleRelease android:clean: desc: Clean Android artifacts cmds: - cd "{{.ANDROID_DIR}}" && ./gradlew clean - rm -rf "{{.PYTHON_SRC_DIR}}/meshchatx" # --- Maintenance --- dist: desc: Alias for dist:linux:appimage cmds: - task: dist:linux:appimage clean: desc: Nuke all build artifacts and dependencies cmds: - rm -rf node_modules build dist python-dist meshchatx/public build-dir out - task: android:clean locales:gen: desc: Generate localization template cmds: - "{{.PYTHON}} scripts/generate_locale_template.py"