feat: flatpak and snap support

This commit is contained in:
zhom committed 2026-09-26 10:39:07 +04:00
1 parent feef010f55
commit 276d5b56f7
17 files changed
+1143

No files matched your search

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2025 zhom@github -->
<component type="desktop-application">
<id>com.donutbrowser.DonutBrowser</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>AGPL-3.0-only</project_license>
<name>Donut Browser</name>
<summary>Open source anti-detect browser</summary>
<developer id="com.donutbrowser">
<name>Donut Browser</name>
</developer>
<description>
<p>
Donut Browser manages any number of isolated browser profiles. Each profile
keeps its own fingerprint, cookies, extensions and data, and runs on
Wayfern, a Chromium-based engine that Donut downloads on first use.
</p>
<ul>
<li>Per-profile HTTP, HTTPS, SOCKS4 and SOCKS5 proxies, and WireGuard configs</li>
<li>Per-profile DNS blocklists for ads and trackers</li>
<li>Profile import from Chrome, Edge, Brave and other Chromium browsers</li>
<li>Cookie and extension management</li>
<li>A local REST API and a Model Context Protocol server for automation</li>
<li>Optional end-to-end encrypted sync to Donut cloud or a self-hosted server</li>
</ul>
</description>
<launchable type="desktop-id">com.donutbrowser.DonutBrowser.desktop</launchable>
<provides>
<binary>donutbrowser</binary>
</provides>
<url type="homepage">https://donutbrowser.com</url>
<url type="bugtracker">https://github.com/zhom/donutbrowser/issues</url>
<url type="vcs-browser">https://github.com/zhom/donutbrowser</url>
<url type="contribute">https://github.com/zhom/donutbrowser/blob/main/CONTRIBUTING.md</url>
<screenshots>
<screenshot type="default">
<image>https://raw.githubusercontent.com/zhom/donutbrowser/main/assets/donut-preview.png</image>
<caption>The profile list</caption>
</screenshot>
</screenshots>
<categories>
<category>Network</category>
<category>WebBrowser</category>
</categories>
<supports>
<control>keyboard</control>
<control>pointing</control>
</supports>
<requires>
<display_length compare="ge">768</display_length>
</requires>
<content_rating type="oars-1.1" />
<releases>
<release version="0.31.2" date="2026-09-23">
<url type="details">https://github.com/zhom/donutbrowser/releases/tag/v0.31.2</url>
</release>
</releases>
</component>
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
# Start a packaged Donut Browser on a virtual display and check that it stays
# up. .github/workflows/linux-packages.yml runs it for the Flatpak and the Snap.
#
# smoke-test.sh <output-dir> <seconds> <command> [args...]
#
# XDG_RUNTIME_DIR must point to a directory owned by the current user. The
# script starts a private session bus at $XDG_RUNTIME_DIR/bus, the path both
# sandboxes let the app reach, and an Xvfb display. It fails when the app exits
# before <seconds> have passed or prints a Rust panic. The app's output and a
# screenshot are left in <output-dir>. A screenshot with almost no colours
# (a blank window) is reported as a warning.
set -euo pipefail
out="$1"
seconds="$2"
shift 2
mkdir -p "$out"
: "${XDG_RUNTIME_DIR:?XDG_RUNTIME_DIR must be set}"
bus="$XDG_RUNTIME_DIR/bus"
rm -f "$bus"
dbus-daemon --session --address="unix:path=$bus" --nofork --nopidfile &
dbus_pid=$!
export DBUS_SESSION_BUS_ADDRESS="unix:path=$bus"
display_number=99
Xvfb ":$display_number" -screen 0 1600x1000x24 -nolisten tcp >"$out/xvfb.log" 2>&1 &
xvfb_pid=$!
export DISPLAY=":$display_number"
trap 'kill "$xvfb_pid" "$dbus_pid" 2>/dev/null || true' EXIT
for _ in $(seq 1 100); do
if [ -S "$bus" ] && [ -S "/tmp/.X11-unix/X$display_number" ]; then
break
fi
sleep 0.1
done
echo "Starting: $*"
"$@" >"$out/app-output.log" 2>&1 &
app_pid=$!
sleep "$seconds"
failed=0
if kill -0 "$app_pid" 2>/dev/null; then
echo "The app is still running after ${seconds}s."
else
code=0
wait "$app_pid" || code=$?
echo "::error::The app exited within ${seconds}s with exit code $code."
failed=1
fi
if command -v import >/dev/null 2>&1; then
import -window root "$out/screenshot.png" || true
colours="$(identify -format '%k' "$out/screenshot.png" 2>/dev/null || echo 0)"
echo "The screenshot has $colours colours."
if [ "$colours" -lt 64 ]; then
echo "::warning::The screenshot has only $colours colours. The window may be blank."
fi
fi
kill "$app_pid" 2>/dev/null || true
for _ in $(seq 1 50); do
kill -0 "$app_pid" 2>/dev/null || break
sleep 0.1
done
kill -9 "$app_pid" 2>/dev/null || true
if grep -n "panicked at" "$out/app-output.log"; then
echo "::error::The app panicked."
failed=1
fi
echo "--- app output (last 100 lines)"
tail -n 100 "$out/app-output.log" || true
exit "$failed"
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env bash
# Check that the Wayfern build Donut downloads can run inside a package's
# sandbox: its libraries resolve there, and it starts headless and answers on
# a DevTools port, which is how Donut drives it.
#
# wayfern-check.sh flatpak|snap <archive> <output-dir>
#
# <archive> is the Wayfern Linux .tar.xz. It is unpacked into the app's own
# data directory, the one place both sandboxes let the app execute files from.
# XDG_RUNTIME_DIR must point to a directory owned by the current user.
set -euo pipefail
kind="$1"
archive="$2"
out="$3"
mkdir -p "$out"
case "$kind" in
flatpak)
app=com.donutbrowser.DonutBrowser
dir="$HOME/.var/app/$app/data/wayfern-check"
in_sandbox() { flatpak run --command=sh "$app" -c "$1"; }
;;
snap)
dir="$HOME/snap/donutbrowser/common/wayfern-check"
in_sandbox() { snap run --shell donutbrowser -c "$1"; }
;;
*)
echo "usage: $0 flatpak|snap <archive> <output-dir>" >&2
exit 2
;;
esac
: "${XDG_RUNTIME_DIR:?XDG_RUNTIME_DIR must be set}"
if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
bus="$XDG_RUNTIME_DIR/bus"
rm -f "$bus"
dbus-daemon --session --address="unix:path=$bus" --nofork --nopidfile &
dbus_pid=$!
trap 'kill "$dbus_pid" 2>/dev/null || true' EXIT
export DBUS_SESSION_BUS_ADDRESS="unix:path=$bus"
for _ in $(seq 1 50); do [ -S "$bus" ] && break; sleep 0.1; done
fi
rm -rf "$dir"
mkdir -p "$dir"
tar -xJf "$archive" -C "$dir"
chrome="$(find "$dir" -type f -name chrome -perm -u+x | head -n 1)"
if [ -z "$chrome" ]; then
echo "::error::The archive has no chrome executable."
exit 1
fi
echo "Wayfern executable: $chrome"
in_sandbox "/lib64/ld-linux-x86-64.so.2 --list '$chrome'" >"$out/wayfern-libraries.txt" 2>&1 || true
if grep "not found" "$out/wayfern-libraries.txt" || ! grep -q "=>" "$out/wayfern-libraries.txt"; then
echo "::error::Wayfern's libraries do not all resolve inside the sandbox."
cat "$out/wayfern-libraries.txt"
exit 1
fi
echo "Every Wayfern library resolves inside the sandbox."
# Donut asks the user to accept the Wayfern terms before the first launch and
# then runs this same command. This runner is thrown away after the job.
in_sandbox "'$chrome' --accept-terms-and-conditions" >"$out/wayfern-terms.log" 2>&1
port=9333
in_sandbox "exec '$chrome' --headless=new --no-sandbox --disable-gpu --disable-dev-shm-usage \
--no-first-run --user-data-dir='$dir/profile' --remote-debugging-address=127.0.0.1 \
--remote-debugging-port=$port about:blank" >"$out/wayfern-output.log" 2>&1 &
wayfern_pid=$!
answered=0
for _ in $(seq 1 60); do
if curl -fsS "http://127.0.0.1:$port/json/version" >"$out/wayfern-version.json" 2>/dev/null; then
answered=1
break
fi
kill -0 "$wayfern_pid" 2>/dev/null || break
sleep 1
done
kill "$wayfern_pid" 2>/dev/null || true
pkill -f "$dir/" 2>/dev/null || true
if [ "$answered" -ne 1 ]; then
echo "::error::Wayfern did not answer on its DevTools port."
tail -n 40 "$out/wayfern-output.log" || true
exit 1
fi
cat "$out/wayfern-version.json"