feat: add Flatpak packaging and private repo helpers
This commit is contained in:
@@ -21,6 +21,9 @@ env/
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
flatpak-build/
|
||||
flatpak-repo/
|
||||
*.flatpak
|
||||
|
||||
# Test caches
|
||||
.pytest_cache/
|
||||
|
||||
@@ -57,7 +57,7 @@ Not implemented yet:
|
||||
- [docker-compose.yml](docker-compose.yml) — local deployment
|
||||
- [requirements.txt](requirements.txt) — Python dependencies
|
||||
- [client.py](client.py) — minimal CLI client
|
||||
- [gtk_client.py](gtk_client.py) — GTK4 desktop client
|
||||
- [cellar-gtk.py](cellar-gtk.py) — GTK4 desktop client
|
||||
- [app/main.py](app/main.py) — API routes
|
||||
- [app/models.py](app/models.py) — SQLAlchemy model
|
||||
- [app/schemas.py](app/schemas.py) — API response schemas
|
||||
@@ -163,6 +163,56 @@ Interactive API docs are available at:
|
||||
|
||||
---
|
||||
|
||||
## Flatpak package
|
||||
|
||||
The repository now includes a Flatpak manifest for the GTK client:
|
||||
|
||||
- [net.enne2.Cellar.yaml](net.enne2.Cellar.yaml)
|
||||
|
||||
Flatpak packaging assets are stored in [flatpak/](flatpak/):
|
||||
|
||||
- desktop entry
|
||||
- AppStream metadata
|
||||
- launcher script
|
||||
- icon generated from [cellar.jpg](cellar.jpg)
|
||||
|
||||
Typical local build flow:
|
||||
|
||||
1. install `flatpak-builder`
|
||||
2. install the required runtimes:
|
||||
- `org.gnome.Platform//47`
|
||||
- `org.gnome.Sdk//47`
|
||||
3. run:
|
||||
|
||||
`flatpak-builder --user --install --force-clean flatpak-build net.enne2.Cellar.yaml`
|
||||
|
||||
Then launch it with:
|
||||
|
||||
`flatpak run net.enne2.Cellar`
|
||||
|
||||
To export a private Flatpak repository and a single-file bundle, use:
|
||||
|
||||
`./scripts/build-flatpak-repo.sh`
|
||||
|
||||
This creates:
|
||||
|
||||
- `flatpak-repo/` — OSTree/Flatpak repository ready to publish
|
||||
- `dist/net.enne2.Cellar.flatpak` — installable Flatpak bundle
|
||||
|
||||
### Publish on `brain.local`
|
||||
|
||||
If `brain.local` serves static files, copy the generated repository there, for example:
|
||||
|
||||
`./scripts/publish-flatpak-repo.sh brain.local /var/www/html/flatpak/cellar`
|
||||
|
||||
Then clients can add the remote and install the app with:
|
||||
|
||||
`flatpak remote-add --if-not-exists --user --no-gpg-verify brain-local http://brain.local/flatpak/cellar`
|
||||
|
||||
`flatpak install --user brain-local net.enne2.Cellar`
|
||||
|
||||
---
|
||||
|
||||
## Environment configuration
|
||||
|
||||
Current environment variables used by the API container:
|
||||
@@ -257,7 +307,7 @@ Use a custom Bottles directory:
|
||||
|
||||
Run:
|
||||
|
||||
`python gtk_client.py`
|
||||
`python cellar-gtk.py`
|
||||
|
||||
The GUI lets you:
|
||||
|
||||
|
||||
+3
-1
@@ -42,6 +42,7 @@ gi.require_version("Adw", "1")
|
||||
from gi.repository import Adw, Gdk, GLib, Gtk # type: ignore[import-not-found]
|
||||
|
||||
# ── Constants ───────────────────────────────────────────────────
|
||||
APP_ID = "net.enne2.Cellar"
|
||||
CONFIG_PATH = Path.home() / ".config" / "cellar" / "gtk_client.json"
|
||||
|
||||
APP_CSS = """\
|
||||
@@ -448,6 +449,7 @@ class CellarWindow(Adw.ApplicationWindow):
|
||||
|
||||
def __init__(self, app: Adw.Application):
|
||||
super().__init__(application=app, title="Cellar")
|
||||
self.set_icon_name(APP_ID)
|
||||
self.config = load_config()
|
||||
self.settings_window: SettingsWindow | None = None
|
||||
self.rows: list[ArchiveRow] = []
|
||||
@@ -824,7 +826,7 @@ class CellarWindow(Adw.ApplicationWindow):
|
||||
# ── Application ─────────────────────────────────────────────────
|
||||
class CellarApplication(Adw.Application):
|
||||
def __init__(self) -> None:
|
||||
super().__init__(application_id="com.cellar.gtkclient")
|
||||
super().__init__(application_id=APP_ID)
|
||||
|
||||
def do_activate(self) -> None:
|
||||
_load_css()
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
export PYTHONPATH="/app/share/cellar${PYTHONPATH:+:$PYTHONPATH}"
|
||||
exec python3 /app/share/cellar/cellar-gtk.py "$@"
|
||||
@@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Cellar
|
||||
Comment=Browse and restore Bottle archives from a Cellar server
|
||||
Exec=cellar
|
||||
Icon=net.enne2.Cellar
|
||||
Terminal=false
|
||||
Categories=Utility;Archiving;GTK;
|
||||
Keywords=bottles;backup;archive;restore;wine;
|
||||
StartupNotify=true
|
||||
StartupWMClass=net.enne2.Cellar
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>net.enne2.Cellar</id>
|
||||
<name>Cellar</name>
|
||||
<summary>Browse and restore Bottle archives from a self-hosted server</summary>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LicenseRef-proprietary</project_license>
|
||||
<developer id="net.enne2">
|
||||
<name>Matteo Benedetto</name>
|
||||
</developer>
|
||||
<launchable type="desktop-id">net.enne2.Cellar.desktop</launchable>
|
||||
<url type="homepage">https://git.enne2.net/enne2/cellar</url>
|
||||
<url type="bugtracker">https://git.enne2.net/enne2/cellar/issues</url>
|
||||
<provides>
|
||||
<binary>cellar</binary>
|
||||
</provides>
|
||||
<description>
|
||||
<p>Cellar is a small GTK application for browsing and restoring archives stored on a self-hosted Bottle archive server.</p>
|
||||
<p>It can refresh the remote catalog, search archives locally, and reinstall archived Bottles environments with progress feedback.</p>
|
||||
</description>
|
||||
<categories>
|
||||
<category>Utility</category>
|
||||
<category>Archiving</category>
|
||||
</categories>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Cellar application artwork</caption>
|
||||
<image type="source" width="1024" height="1024">https://git.enne2.net/enne2/cellar/raw/branch/master/cellar.jpg</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#5b0f11</color>
|
||||
<color type="primary" scheme_preference="dark">#d8b27d</color>
|
||||
</branding>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="1.0.0" date="2026-03-08" />
|
||||
</releases>
|
||||
</component>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 739 KiB |
@@ -0,0 +1,27 @@
|
||||
app-id: net.enne2.Cellar
|
||||
branch: stable
|
||||
runtime: org.gnome.Platform
|
||||
runtime-version: '47'
|
||||
sdk: org.gnome.Sdk
|
||||
command: cellar
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
- --share=network
|
||||
- --socket=wayland
|
||||
- --socket=fallback-x11
|
||||
- --device=dri
|
||||
- --filesystem=home
|
||||
modules:
|
||||
- name: cellar
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- install -Dm755 flatpak/cellar-launcher.sh /app/bin/cellar
|
||||
- install -Dm644 cellar-gtk.py /app/share/cellar/cellar-gtk.py
|
||||
- install -Dm644 client.py /app/share/cellar/client.py
|
||||
- install -Dm644 cellar.jpg /app/share/cellar/cellar.jpg
|
||||
- install -Dm644 flatpak/net.enne2.Cellar.desktop /app/share/applications/net.enne2.Cellar.desktop
|
||||
- install -Dm644 flatpak/net.enne2.Cellar.metainfo.xml /app/share/metainfo/net.enne2.Cellar.metainfo.xml
|
||||
- install -Dm644 flatpak/net.enne2.Cellar.png /app/share/icons/hicolor/512x512/apps/net.enne2.Cellar.png
|
||||
sources:
|
||||
- type: dir
|
||||
path: .
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
APP_ID="net.enne2.Cellar"
|
||||
BRANCH="stable"
|
||||
MANIFEST="${ROOT_DIR}/net.enne2.Cellar.yaml"
|
||||
BUILD_DIR="${ROOT_DIR}/flatpak-build"
|
||||
REPO_DIR="${ROOT_DIR}/flatpak-repo"
|
||||
BUNDLE_PATH="${ROOT_DIR}/dist/${APP_ID}.flatpak"
|
||||
|
||||
if ! command -v flatpak-builder >/dev/null 2>&1; then
|
||||
echo "flatpak-builder not found. Install it first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v flatpak >/dev/null 2>&1; then
|
||||
echo "flatpak not found. Install it first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "${ROOT_DIR}/dist"
|
||||
rm -rf "${BUILD_DIR}"
|
||||
mkdir -p "${REPO_DIR}"
|
||||
|
||||
flatpak-builder \
|
||||
--force-clean \
|
||||
--repo="${REPO_DIR}" \
|
||||
"${BUILD_DIR}" \
|
||||
"${MANIFEST}"
|
||||
|
||||
flatpak build-bundle "${REPO_DIR}" "${BUNDLE_PATH}" "${APP_ID}" "${BRANCH}"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Flatpak repository ready:
|
||||
${REPO_DIR}
|
||||
|
||||
Flatpak bundle ready:
|
||||
${BUNDLE_PATH}
|
||||
|
||||
Example private remote setup:
|
||||
flatpak remote-add --if-not-exists --user --no-gpg-verify brain-local http://brain.local/flatpak/cellar
|
||||
flatpak install --user brain-local ${APP_ID}
|
||||
EOF
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 2 || $# -gt 3 ]]; then
|
||||
echo "Usage: $0 <host> <remote-path> [public-url]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
REPO_DIR="${ROOT_DIR}/flatpak-repo"
|
||||
HOST="$1"
|
||||
REMOTE_PATH="$2"
|
||||
PUBLIC_URL="${3:-}"
|
||||
|
||||
if [[ ! -d "${REPO_DIR}" ]]; then
|
||||
echo "Repository not found at ${REPO_DIR}. Run ./scripts/build-flatpak-repo.sh first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v rsync >/dev/null 2>&1; then
|
||||
echo "rsync not found. Install it first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rsync -av --delete "${REPO_DIR}/" "${HOST}:${REMOTE_PATH%/}/"
|
||||
|
||||
if [[ -n "${PUBLIC_URL}" ]]; then
|
||||
cat <<EOF
|
||||
|
||||
Published to ${HOST}:${REMOTE_PATH}
|
||||
|
||||
Clients can add the remote with:
|
||||
flatpak remote-add --if-not-exists --user --no-gpg-verify brain-local ${PUBLIC_URL}
|
||||
EOF
|
||||
else
|
||||
echo
|
||||
echo "Published to ${HOST}:${REMOTE_PATH}"
|
||||
fi
|
||||
Reference in New Issue
Block a user