feat(linux): bundle Python CLI and fix Electron packaged build
- contrib/linux/Dockerfile: add libpython3.11 + PyInstaller to build standalone cli binary; fix venv isolation via .dockerignore - frontend/electron/main.cjs: use bundled cli binary in prod via process.resourcesPath, fallback to venv/python3 in dev - frontend/package.json: add extraResources for cli binary, set output dir to release/ - frontend/vite.config.js: set base './' for file:// protocol in prod - .dockerignore: exclude venv/, node_modules/, dist/, .git/ - .gitignore: ignore release/ output directories
This commit is contained in:
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@@ -0,0 +1,10 @@
|
||||
venv/
|
||||
.venv/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
node_modules/
|
||||
frontend/node_modules/
|
||||
frontend/dist/
|
||||
frontend/release/
|
||||
release/
|
||||
.git/
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -20,3 +20,5 @@ __pycache__/
|
||||
node_modules/
|
||||
frontend/node_modules/
|
||||
frontend/dist/
|
||||
frontend/release/
|
||||
release/
|
||||
|
||||
31
contrib/linux/Dockerfile
Normal file
31
contrib/linux/Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
FROM node:22.14.0-bookworm
|
||||
|
||||
# System dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python3 python3-pip python3-venv libpython3.11 \
|
||||
binutils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy repo
|
||||
COPY . .
|
||||
|
||||
# Python venv + dependencies
|
||||
RUN python3 -m venv venv && \
|
||||
venv/bin/pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Compile Python CLI into a standalone binary
|
||||
RUN venv/bin/pip install --no-cache-dir pyinstaller && \
|
||||
venv/bin/pyinstaller --onefile --name cli src/cli.py && \
|
||||
mkdir -p frontend/resources && \
|
||||
cp dist/cli frontend/resources/cli
|
||||
|
||||
# JS dependencies + electron-builder
|
||||
RUN cd frontend && npm ci && npm install --no-save electron-builder
|
||||
|
||||
# Build
|
||||
RUN cd frontend && npx vite build && npx electron-builder --linux AppImage --publish never
|
||||
|
||||
# Export AppImage
|
||||
CMD cp frontend/release/*.AppImage /out/
|
||||
18
contrib/linux/build.sh
Executable file
18
contrib/linux/build.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT=$(cd "$(dirname "$0")/../.." && pwd)
|
||||
OUT_DIR="$REPO_ROOT/release"
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
docker build -t wallet-generator-builder \
|
||||
-f "$REPO_ROOT/contrib/linux/Dockerfile" \
|
||||
"$REPO_ROOT"
|
||||
|
||||
docker run --rm \
|
||||
-v "$OUT_DIR:/out" \
|
||||
wallet-generator-builder
|
||||
|
||||
echo "AppImage saved to: $OUT_DIR"
|
||||
ls "$OUT_DIR"/*.AppImage
|
||||
@@ -48,21 +48,24 @@ function resolveWalletFile(kind, filename) {
|
||||
return filePath
|
||||
}
|
||||
|
||||
// ── Resolve Python executable ──────────────────────────────────────────────────
|
||||
function findPython() {
|
||||
// ── Resolve CLI command (dev: python + cli.py, prod: bundled binary) ──────────
|
||||
function getCliCommand() {
|
||||
if (!isDev) {
|
||||
const bundled = path.join(process.resourcesPath, 'cli')
|
||||
if (fs.existsSync(bundled)) return { exec: bundled, baseArgs: [] }
|
||||
}
|
||||
const repoRoot = path.join(__dirname, '..', '..')
|
||||
const venvPython = path.join(repoRoot, 'venv', 'bin', 'python')
|
||||
return fs.existsSync(venvPython) ? venvPython : 'python3'
|
||||
const python = fs.existsSync(path.join(repoRoot, 'venv', 'bin', 'python'))
|
||||
? path.join(repoRoot, 'venv', 'bin', 'python')
|
||||
: 'python3'
|
||||
return { exec: python, baseArgs: [path.join(repoRoot, 'src', 'cli.py')] }
|
||||
}
|
||||
|
||||
// ── Call Python CLI ────────────────────────────────────────────────────────────
|
||||
function callPython(command, args = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const python = findPython()
|
||||
const repoRoot = path.join(__dirname, '..', '..')
|
||||
const cliPath = path.join(repoRoot, 'src', 'cli.py')
|
||||
|
||||
execFile(python, [cliPath, command, JSON.stringify(args)], { cwd: repoRoot }, (err, stdout, stderr) => {
|
||||
const { exec, baseArgs } = getCliCommand()
|
||||
execFile(exec, [...baseArgs, command, JSON.stringify(args)], (err, stdout, stderr) => {
|
||||
if (err) { reject(new Error(stderr || err.message)); return }
|
||||
try {
|
||||
const result = JSON.parse(stdout.trim())
|
||||
@@ -139,7 +142,7 @@ function createWindow() {
|
||||
height: 750,
|
||||
minWidth: 320,
|
||||
minHeight: 480,
|
||||
title: 'Wallet Generator',
|
||||
title: 'wallet-gen',
|
||||
backgroundColor: '#0f1117',
|
||||
icon: path.join(__dirname, '..', 'public', 'icons', 'icon.png'),
|
||||
webPreferences: {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/icons/bitcoin.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Wallet Generator</title>
|
||||
<title>wallet-gen</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "wallet-generator",
|
||||
"name": "wallet-gen",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
@@ -12,10 +12,16 @@
|
||||
"dist": "vite build && electron-builder"
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.walletgenerator.app",
|
||||
"productName": "Wallet Generator",
|
||||
"appId": "com.walletgen.app",
|
||||
"productName": "wallet-gen",
|
||||
"icon": "public/icons/icon.png",
|
||||
"files": ["dist/**", "electron/**"],
|
||||
"extraResources": [
|
||||
{ "from": "resources/cli", "to": "cli" }
|
||||
],
|
||||
"directories": {
|
||||
"output": "release"
|
||||
},
|
||||
"linux": {
|
||||
"target": "AppImage",
|
||||
"category": "Finance"
|
||||
|
||||
@@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
base: './',
|
||||
server: {
|
||||
port: 5173,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user