mirror of
https://github.com/BillyOutlast/gsd-pi-config.git
synced 2026-07-01 08:34:05 -04:00
feat: add Flatpak packaging
- Add Flatpak manifest (com.opengsd.pi.yaml) using GNOME 48 SDK - Add tauri-plugin-localhost to serve bundled assets via HTTP since the tauri:// custom protocol doesn't work in WebKit2GTK Flatpak sandbox - Use npx tauri build (not cargo build) to properly embed frontend assets into the binary - Vendor npm + Cargo deps on host to work around DNS resolution failure in bubblewrap sandbox (127.0.0.53 unreachable) - Set WEBKIT_DISABLE_DMABUF_RENDERER=1 to fix Wayland crash - Add desktop entry, AppStream metadata, and SVG icon - Add build.sh and create-bundle.sh helper scripts - Update README with Flatpak build instructions
This commit is contained in:
+36
@@ -28,3 +28,39 @@ Thumbs.db
|
||||
.idea/
|
||||
*.swp
|
||||
.vercel
|
||||
|
||||
# ── GSD baseline (auto-generated) ──
|
||||
.gsd
|
||||
.gsd-id
|
||||
.mcp.json
|
||||
.bg-shell/
|
||||
nul
|
||||
nul.*
|
||||
con
|
||||
con.*
|
||||
prn
|
||||
prn.*
|
||||
aux
|
||||
aux.*
|
||||
com[1-9]
|
||||
com[1-9].*
|
||||
lpt[1-9]
|
||||
lpt[1-9].*
|
||||
*.swo
|
||||
*~
|
||||
*.code-workspace
|
||||
.env.*
|
||||
!.env.example
|
||||
.next/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
venv/
|
||||
target/
|
||||
vendor/
|
||||
coverage/
|
||||
.cache/
|
||||
tmp/
|
||||
.agents/
|
||||
|
||||
flatpak/cargo-vendor/
|
||||
@@ -91,6 +91,21 @@ npm run tauri build
|
||||
|
||||
Bundles land in `src-tauri/target/release/bundle/`.
|
||||
|
||||
### Build a Flatpak
|
||||
|
||||
```bash
|
||||
cd flatpak
|
||||
./build.sh
|
||||
```
|
||||
|
||||
This vendors all npm and Cargo dependencies on the host (required because the Flatpak sandbox can't resolve DNS), then builds inside the sandbox with `npx tauri build --no-bundle` so frontend assets are properly embedded. The `tauri-plugin-localhost` serves the bundled assets at runtime since the `tauri://` custom protocol doesn't work inside WebKit2GTK in the Flatpak sandbox.
|
||||
|
||||
```bash
|
||||
flatpak run com.opengsd.pi
|
||||
```
|
||||
|
||||
See `flatpak/README.md` for prerequisites and details.
|
||||
|
||||
## Keyboard shortcuts
|
||||
|
||||
| Shortcut | Action |
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# Flatpak Build
|
||||
|
||||
This directory contains the Flatpak packaging for Pi.
|
||||
|
||||
## Files
|
||||
|
||||
- `com.opengsd.pi.yaml` - Flatpak manifest (uses GNOME 48 SDK for webkit2gtk-4.1)
|
||||
- `com.opengsd.pi.desktop` - Desktop entry file
|
||||
- `com.opengsd.pi.metainfo.xml` - AppStream metadata
|
||||
- `com.opengsd.pi.svg` - Application icon
|
||||
- `cargo-config.toml` - Cargo config for vendored dependencies
|
||||
- `build.sh` - Vendor crates + build + install locally
|
||||
- `create-bundle.sh` - Create bundle for distribution
|
||||
|
||||
## Why vendored crates?
|
||||
|
||||
The flatpak-builder sandbox isolates loopback networking, which breaks
|
||||
DNS resolution when `/etc/resolv.conf` points to `127.0.0.53`
|
||||
(systemd-resolved stub). Rather than modifying system DNS, we vendor
|
||||
all Cargo crates on the host and build with `--offline`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
```bash
|
||||
# Install flatpak and flatpak-builder
|
||||
sudo apt install flatpak flatpak-builder
|
||||
|
||||
# Add Flathub
|
||||
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
|
||||
# Install GNOME SDK (includes webkit2gtk-4.1)
|
||||
flatpak install flathub org.gnome.Sdk//48 org.gnome.Platform//48
|
||||
```
|
||||
|
||||
## Build & Install Locally
|
||||
|
||||
```bash
|
||||
cd flatpak
|
||||
./build.sh
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
flatpak run com.opengsd.pi
|
||||
```
|
||||
|
||||
## Create Bundle for Distribution
|
||||
|
||||
```bash
|
||||
./create-bundle.sh
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Uses `org.gnome.Platform//48` runtime (includes webkit2gtk-4.1, GTK3, libsoup)
|
||||
- Rust SDK extension is included via `append-path`
|
||||
- Keyring access via `--filesystem=xdg-run/keyring`
|
||||
- Network access enabled for updater functionality
|
||||
- Binary is renamed from `gsd-pi-config` to `pi` in the Flatpak
|
||||
|
||||
## Flathub Submission
|
||||
|
||||
For Flathub submission, you'll need to:
|
||||
|
||||
1. Fork the flathub/com.opengsd.pi repository
|
||||
2. Update the manifest to use git source instead of local dir
|
||||
3. Add GPG signing
|
||||
4. Submit PR to Flathub
|
||||
|
||||
See: https://docs.flathub.org/flatpak-prerequisites/
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# Build script for Flatpak
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
echo "=== Vendoring npm dependencies ==="
|
||||
cd "$PROJECT_DIR"
|
||||
rm -rf node_modules
|
||||
npm ci 2>&1 | tail -5
|
||||
|
||||
echo ""
|
||||
echo "=== Vendoring Cargo crates ==="
|
||||
rm -rf flatpak/cargo-vendor
|
||||
cargo vendor --versioned-dirs --manifest-path src-tauri/Cargo.toml flatpak/cargo-vendor 2>&1 | tail -3
|
||||
|
||||
echo ""
|
||||
echo "=== Building Flatpak ==="
|
||||
cd "$SCRIPT_DIR"
|
||||
rm -rf .flatpak-builder build-dir
|
||||
flatpak-builder --user --install --force-clean build-dir com.opengsd.pi.yaml
|
||||
|
||||
echo ""
|
||||
echo "Done! Run with: flatpak run com.opengsd.pi"
|
||||
@@ -0,0 +1,5 @@
|
||||
[source.crates-io]
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source.vendored-sources]
|
||||
directory = "src-tauri/vendor"
|
||||
@@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Name=Pi
|
||||
Exec=pi
|
||||
Icon=com.opengsd.pi
|
||||
Type=Application
|
||||
Categories=Development;Utility;
|
||||
Keywords=tauri;desktop;config;
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>com.opengsd.pi</id>
|
||||
<metadata_license>MIT</metadata_license>
|
||||
<project_license>MIT</project_license>
|
||||
<name>Pi</name>
|
||||
<summary>A Tauri v2 desktop application</summary>
|
||||
<description>
|
||||
<p>
|
||||
Pi is a desktop application built with Tauri v2.
|
||||
It provides a modern, secure interface for configuration and management.
|
||||
</p>
|
||||
</description>
|
||||
<url type="homepage">https://github.com/open-gsd/gsd-pi-config</url>
|
||||
<url type="bugtracker">https://github.com/open-gsd/gsd-pi-config/issues</url>
|
||||
<provides>
|
||||
<binary>pi</binary>
|
||||
</provides>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="0.1.0" date="2026-06-02">
|
||||
<description>
|
||||
<p>Initial release with basic functionality.</p>
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
</component>
|
||||
@@ -0,0 +1,50 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1024" height="1024">
|
||||
<defs>
|
||||
<!-- Background gradient: deep black with subtle cyan tint at top -->
|
||||
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" stop-color="#0a1420"/>
|
||||
<stop offset="40%" stop-color="#000000"/>
|
||||
<stop offset="100%" stop-color="#000000"/>
|
||||
</linearGradient>
|
||||
|
||||
<!-- Cyan glow filter -->
|
||||
<filter id="cyanGlow" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="28" result="blur"/>
|
||||
<feFlood flood-color="#7dcfff" flood-opacity="0.6"/>
|
||||
<feComposite in2="blur" operator="in" result="glow"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="glow"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<!-- Inner stroke highlight -->
|
||||
<linearGradient id="strokeGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" stop-color="rgba(125, 207, 255, 0.3)"/>
|
||||
<stop offset="100%" stop-color="rgba(125, 207, 255, 0.05)"/>
|
||||
</linearGradient>
|
||||
|
||||
<style>
|
||||
.wordmark {
|
||||
font-family: 'SF Mono', 'JetBrains Mono', 'Fira Code', 'Menlo', monospace;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.04em;
|
||||
fill: #7dcfff;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<!-- Rounded square background (macOS convention ~22% corner radius) -->
|
||||
<rect x="0" y="0" width="1024" height="1024" rx="224" ry="224" fill="url(#bgGrad)"/>
|
||||
|
||||
<!-- Inner stroke for depth -->
|
||||
<rect x="4" y="4" width="1016" height="1016" rx="220" ry="220"
|
||||
fill="none" stroke="url(#strokeGrad)" stroke-width="2"/>
|
||||
|
||||
<!-- Giant "2" with glow, perfectly centered -->
|
||||
<g filter="url(#cyanGlow)">
|
||||
<text class="wordmark" x="512" y="720" font-size="760" text-anchor="middle">
|
||||
2
|
||||
</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,66 @@
|
||||
app-id: com.opengsd.pi
|
||||
runtime: org.gnome.Platform
|
||||
runtime-version: '48'
|
||||
sdk: org.gnome.Sdk
|
||||
command: pi
|
||||
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
- --socket=fallback-x11
|
||||
- --socket=wayland
|
||||
- --socket=pulseaudio
|
||||
- --device=dri
|
||||
- --filesystem=xdg-run/keyring
|
||||
- --share=network
|
||||
- --env=WEBKIT_DISABLE_DMABUF_RENDERER=1
|
||||
|
||||
build-options:
|
||||
env:
|
||||
CARGO_HOME: /run/build/pi/cargo
|
||||
|
||||
modules:
|
||||
# Node.js runtime
|
||||
- name: nodejs
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- mkdir -p /app/share/nodejs
|
||||
- mv * /app/share/nodejs/
|
||||
- mkdir -p /app/bin
|
||||
- ln -s /app/share/nodejs/bin/node /app/bin/node
|
||||
- ln -s /app/share/nodejs/bin/npm /app/bin/npm
|
||||
- ln -s /app/share/nodejs/bin/npx /app/bin/npx
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://nodejs.org/dist/v22.16.0/node-v22.16.0-linux-x64.tar.xz
|
||||
sha256: f4cb75bb036f0d0eddf6b79d9596df1aaab9ddccd6a20bf489be5abe9467e84e
|
||||
|
||||
# Build everything in one module (frontend + Tauri with asset embedding)
|
||||
- name: pi
|
||||
buildsystem: simple
|
||||
build-options:
|
||||
append-path: /app/share/nodejs/bin:/usr/lib/sdk/rust-stable/bin
|
||||
build-commands:
|
||||
# Build frontend
|
||||
- npm run build
|
||||
# Build with tauri — this embeds frontend assets into the binary
|
||||
- mkdir -p .cargo
|
||||
- cp cargo-config.toml .cargo/config.toml
|
||||
- CARGO_NET_OFFLINE=true npx tauri build --no-bundle
|
||||
# Install binary
|
||||
- mkdir -p ${FLATPAK_DEST}/bin
|
||||
- cp src-tauri/target/release/gsd-pi-config ${FLATPAK_DEST}/bin/pi
|
||||
# Install desktop/icon/metadata
|
||||
- mkdir -p ${FLATPAK_DEST}/share/applications
|
||||
- cp flatpak/com.opengsd.pi.desktop ${FLATPAK_DEST}/share/applications/
|
||||
- mkdir -p ${FLATPAK_DEST}/share/icons/hicolor/scalable/apps
|
||||
- cp flatpak/com.opengsd.pi.svg ${FLATPAK_DEST}/share/icons/hicolor/scalable/apps/
|
||||
- mkdir -p ${FLATPAK_DEST}/share/metainfo
|
||||
- cp flatpak/com.opengsd.pi.metainfo.xml ${FLATPAK_DEST}/share/metainfo/
|
||||
sources:
|
||||
- type: dir
|
||||
path: ..
|
||||
- type: dir
|
||||
path: cargo-vendor
|
||||
dest: src-tauri/vendor
|
||||
- type: file
|
||||
path: cargo-config.toml
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
# Create a release bundle for Flathub submission
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Build
|
||||
flatpak-builder --repo=repo --force-clean build-dir com.opengsd.pi.yaml
|
||||
|
||||
# Create bundle
|
||||
flatpak build-bundle repo com.opengsd.pi.flatpak com.opengsd.pi
|
||||
|
||||
echo "Bundle created: flatpak/com.opengsd.pi.flatpak"
|
||||
echo "Upload to Flathub or host on your own repo."
|
||||
Generated
+56
@@ -90,6 +90,12 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "ascii"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
|
||||
|
||||
[[package]]
|
||||
name = "async-broadcast"
|
||||
version = "0.7.2"
|
||||
@@ -575,6 +581,12 @@ dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chunked_transfer"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
@@ -1558,12 +1570,14 @@ dependencies = [
|
||||
"dirs",
|
||||
"keyring",
|
||||
"log",
|
||||
"portpicker",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-dialog",
|
||||
"tauri-plugin-localhost",
|
||||
"tauri-plugin-log",
|
||||
"tauri-plugin-opener",
|
||||
"tauri-plugin-process",
|
||||
@@ -1732,6 +1746,12 @@ version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.9.0"
|
||||
@@ -2966,6 +2986,15 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portpicker"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9"
|
||||
dependencies = [
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.5"
|
||||
@@ -4383,6 +4412,21 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-localhost"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c8d72c024121b1a3d9268293d49a56baf01a8c785561c85d17872588b839e55"
|
||||
dependencies = [
|
||||
"http",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"thiserror 2.0.18",
|
||||
"tiny_http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-log"
|
||||
version = "2.8.0"
|
||||
@@ -4677,6 +4721,18 @@ dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny_http"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"chunked_transfer",
|
||||
"httpdate",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.3"
|
||||
|
||||
@@ -28,6 +28,8 @@ tauri-plugin-updater = "2"
|
||||
tauri-plugin-process = "2"
|
||||
dirs = "6"
|
||||
keyring = { version = "3", features = ["apple-native", "linux-native", "windows-native"] }
|
||||
tauri-plugin-localhost = "2.3.2"
|
||||
portpicker = "0.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
|
||||
+12
-1
@@ -966,7 +966,18 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_updater::Builder::new().build())
|
||||
.plugin(tauri_plugin_process::init())
|
||||
.setup(|app| {
|
||||
.plugin(tauri_plugin_localhost::Builder::new(5173).build())
|
||||
.setup(move |app| {
|
||||
#[cfg(not(dev))]
|
||||
{
|
||||
let url: tauri::Url = "http://localhost:5173".parse().unwrap();
|
||||
tauri::WebviewWindowBuilder::new(app, "main".to_string(), tauri::WebviewUrl::External(url))
|
||||
.title("GSD Pi Config")
|
||||
.inner_size(1100.0, 750.0)
|
||||
.min_inner_size(800.0, 600.0)
|
||||
.resizable(true)
|
||||
.build()?;
|
||||
}
|
||||
if cfg!(debug_assertions) {
|
||||
app.handle().plugin(
|
||||
tauri_plugin_log::Builder::default()
|
||||
|
||||
@@ -10,18 +10,7 @@
|
||||
"beforeBuildCommand": "npm run build"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "GSD Pi Config",
|
||||
"width": 1100,
|
||||
"height": 750,
|
||||
"minWidth": 800,
|
||||
"minHeight": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false,
|
||||
"decorations": true
|
||||
}
|
||||
],
|
||||
"windows": [],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user