Refactor Docker setup and frontend structure

- Updated Dockerfile to copy frontend files to meshchatx/public directory.
- Modified .dockerignore to include meshchatx/public.
- Added a new script to prepare the frontend directory.
- Adjusted Vite configuration to output to the new public directory.
- Updated GitHub Actions workflow to reflect changes in build process and artifact handling.
This commit is contained in:
2025-11-30 23:34:45 -06:00
parent 2e001006c9
commit 0b0a39ea86
9 changed files with 126 additions and 130 deletions

View File

@@ -15,6 +15,7 @@ Makefile
build/
dist/
public/
meshchatx/public/
node_modules/
__pycache__/
*.py[cod]

View File

@@ -27,102 +27,14 @@ on:
default: 'true'
type: boolean
permissions:
contents: read
jobs:
build_windows:
runs-on: windows-latest
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.build_windows == 'true')
permissions:
contents: write
steps:
- name: Clone Repo
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
- name: Install NodeJS
uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
with:
node-version: 22
- name: Install Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
- name: Install Poetry
run: python -m pip install --upgrade pip poetry
- name: Sync versions
run: python scripts/sync_version.py
- name: Install Python Deps
run: python -m poetry install
- name: Install NodeJS Deps
run: npm install
- name: Build Electron App
run: npm run dist
- name: Create Release
id: create_release
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
with:
draft: true
allowUpdates: true
replacesArtifacts: true
omitDraftDuringUpdate: true
omitNameDuringUpdate: true
artifacts: "dist/*-win-installer.exe,dist/*-win-portable.exe"
build_mac:
runs-on: macos-13
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.build_mac == 'true')
permissions:
contents: write
steps:
- name: Clone Repo
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
- name: Install NodeJS
uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
with:
node-version: 18
- name: Install Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.11"
- name: Install Poetry
run: python -m pip install --upgrade pip poetry
- name: Sync versions
run: python scripts/sync_version.py
- name: Install Python Deps
run: python -m poetry install
- name: Install NodeJS Deps
run: npm install
- name: Build Electron App
run: npm run dist
- name: Create Release
id: create_release
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
with:
draft: true
allowUpdates: true
replacesArtifacts: true
omitDraftDuringUpdate: true
omitNameDuringUpdate: true
artifacts: "dist/*-mac.dmg"
build_linux:
build_frontend:
runs-on: ubuntu-latest
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.build_linux == 'true')
permissions:
contents: write
contents: read
steps:
- name: Clone Repo
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
@@ -137,33 +49,108 @@ jobs:
with:
python-version: "3.12"
- name: Sync versions
run: python scripts/sync_version.py
- name: Install NodeJS Deps
run: npm install
- name: Build Frontend
run: npm run build-frontend
- name: Upload frontend artifact
uses: actions/upload-artifact@v4
with:
name: frontend-build
path: meshchatx/public
if-no-files-found: error
build_desktop:
name: Build Desktop (${{ matrix.name }})
needs: build_frontend
runs-on: ${{ matrix.os }}
if: |
github.event_name == 'push' ||
(
github.event_name == 'workflow_dispatch' &&
(
(matrix.name == 'windows' && github.event.inputs.build_windows == 'true') ||
(matrix.name == 'mac' && github.event.inputs.build_mac == 'true') ||
(matrix.name == 'linux' && github.event.inputs.build_linux == 'true')
)
)
strategy:
fail-fast: false
matrix:
include:
- name: windows
os: windows-latest
node: 22
python: "3.12"
release_artifacts: "dist/*-win-installer.exe,dist/*-win-portable.exe"
- name: mac
os: macos-13
node: 18
python: "3.11"
release_artifacts: "dist/*-mac.dmg"
- name: linux
os: ubuntu-latest
node: 22
python: "3.12"
release_artifacts: "dist/*-linux.AppImage,dist/*-linux.deb,python-dist/*.whl"
permissions:
contents: write
steps:
- name: Clone Repo
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
- name: Install NodeJS
uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
with:
node-version: ${{ matrix.node }}
- name: Install Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: ${{ matrix.python }}
- name: Install Poetry
run: python -m pip install --upgrade pip poetry
- name: Sync versions
run: python scripts/sync_version.py
- name: Install Python Deps
run: python -m poetry install
- name: Install NodeJS Deps
run: npm install
- name: Prepare frontend directory
run: python scripts/prepare_frontend_dir.py
- name: Download frontend artifact
uses: actions/download-artifact@v4
with:
name: frontend-build
path: meshchatx/public
- name: Install patchelf
if: matrix.name == 'linux'
run: sudo apt-get update && sudo apt-get install -y patchelf
- name: Install Poetry
run: python -m pip install --upgrade pip poetry
- name: Sync versions
run: python scripts/sync_version.py
- name: Install Python Deps
run: python -m poetry install
- name: Build Python wheel
if: matrix.name == 'linux'
run: |
python -m poetry build -f wheel
mkdir -p python-dist
mv dist/*.whl python-dist/
rm -rf dist
- name: Install NodeJS Deps
run: npm install
- name: Build Electron App
run: npm run dist
run: npm run dist-prebuilt
- name: Create Release
id: create_release
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
with:
draft: true
@@ -171,7 +158,7 @@ jobs:
replacesArtifacts: true
omitDraftDuringUpdate: true
omitNameDuringUpdate: true
artifacts: "dist/*-linux.AppImage,dist/*-linux.deb,python-dist/*.whl"
artifacts: ${{ matrix.release_artifacts }}
build_docker:
runs-on: ubuntu-latest

View File

@@ -10,9 +10,8 @@ FROM node:${NODE_VERSION}-alpine@${NODE_ALPINE_SHA256} AS build-frontend
WORKDIR /src
# Copy required source files
COPY *.json .
COPY *.js .
COPY src/frontend ./src/frontend
COPY package*.json vite.config.js ./
COPY meshchatx ./meshchatx
# Install NodeJS deps, exluding electron
RUN npm install --omit=dev && \
@@ -34,12 +33,10 @@ RUN apk add --no-cache --virtual .build-deps \
apk del .build-deps
# Copy prebuilt frontend
COPY --from=build-frontend /src/public public
COPY --from=build-frontend /src/meshchatx/public meshchatx/public
# Copy other required source files
COPY *.py .
COPY src/__init__.py ./src/__init__.py
COPY src/backend ./src/backend
COPY *.json .
COPY meshchatx ./meshchatx
COPY pyproject.toml poetry.lock ./
CMD ["python", "meshchat.py", "--host=0.0.0.0", "--reticulum-config-dir=/config/.reticulum", "--storage-dir=/config/.meshchat", "--headless"]
CMD ["python", "-m", "meshchatx.meshchat", "--host=0.0.0.0", "--reticulum-config-dir=/config/.reticulum", "--storage-dir=/config/.meshchat", "--headless"]

View File

@@ -39,6 +39,7 @@ clean:
rm -rf build
rm -rf dist
rm -rf python-dist
rm -rf meshchatx/public
sync-version:
$(PYTHON) scripts/sync_version.py

View File

@@ -49,20 +49,19 @@ def get_file_path(filename):
datadir = os.path.dirname(sys.executable)
return os.path.join(datadir, filename)
# Running from source or an installed wheel: assets live inside the meshchatx package
# Assets live inside the meshchatx package when installed from a wheel
package_dir = os.path.dirname(__file__)
test_path = os.path.join(package_dir, filename)
if os.path.exists(test_path):
return test_path
package_path = os.path.join(package_dir, filename)
if os.path.exists(package_path):
return package_path
# Fall back to repo root when running directly from the source tree
# When running from the repository, fall back to the project root
repo_root = os.path.dirname(package_dir)
repo_path = os.path.join(repo_root, filename)
if os.path.exists(repo_path):
return repo_path
# Return the package path even if it does not exist so callers raise a clear error
return test_path
return package_path
class ReticulumMeshChat:

View File

@@ -11,7 +11,8 @@
"build": "npm run build-frontend && npm run build-backend",
"electron-postinstall": "electron-builder install-app-deps",
"electron": "npm run electron-postinstall && npm run build && electron .",
"dist": "npm run electron-postinstall && npm run build && electron-builder --publish=never"
"dist": "npm run electron-postinstall && npm run build && electron-builder --publish=never",
"dist-prebuilt": "npm run electron-postinstall && npm run build-backend && electron-builder --publish=never"
},
"license": "MIT",
"engines": {

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python3
from pathlib import Path
import shutil
TARGET = Path("meshchatx") / "public"
if TARGET.exists():
shutil.rmtree(TARGET)
TARGET.mkdir(parents=True, exist_ok=True)

View File

@@ -28,8 +28,7 @@ print(f'meshchat module location: {meshchat.__file__}')
# Check if public directory exists
meshchat_dir = os.path.dirname(meshchat.__file__)
package_dir = os.path.dirname(os.path.dirname(meshchat_dir))
public_path = os.path.join(package_dir, 'public')
public_path = os.path.join(meshchat_dir, 'public')
print(f'Checking for public at: {public_path}')
print(f'Exists: {os.path.exists(public_path)}')
@@ -45,7 +44,7 @@ if os.path.exists(test_path):
else:
print('WARNING: public directory not found!')
print('Checking parent directories...')
current = package_dir
current = meshchat_dir
for i in range(3):
test = os.path.join(current, 'public')
print(f' {test}: {os.path.exists(test)}')

View File

@@ -14,8 +14,8 @@ export default {
build: {
// we want to compile vite app to /public which is bundled and served by the python executable
outDir: path.join(__dirname, "public"),
// we want to compile vite app to meshchatx/public which is bundled and served by the python executable
outDir: path.join(__dirname, "meshchatx", "public"),
emptyOutDir: true,
rollupOptions: {