desktop: prebuilt pacman package + verified .deb (tasks 2022, 2074)
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 3m41s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 3m41s
Native packages the installer can actually fetch, before task 2014 wires up the fetching. Arch (task 2022, re-scoped): the source PKGBUILD is gone — asking every user to install rust+node and compile for minutes isn't distribution. Replaced by desktop/packaging/arch/package-prebuilt.sh, which wraps the binary the Linux job already built into a .pkg.tar.zst. No second Rust build, no Arch CI image: the binary bundles nothing and resolves webkit/gtk/soup by soname, identical on both distros, with SQLite compiled in and glibc used in the safe built-old/run-new direction. CI is Debian and has no pacman, so the step logs .PKGINFO plus the full file listing for audit instead of pretending to verify. Debian (task 2074): install.sh hands the .deb to every Debian/Ubuntu user and nothing had ever inspected it. tauri.conf.json now declares libwebkit2gtk-4.1-0 + libgtk-3-0 explicitly rather than trusting inference — and deliberately declares no appindicator or sqlite dep, since tauri is built with features=[] and rusqlite is "bundled". desktop/packaging/deb/verify.sh prints the generated control file, cross-checks it against what the ELF actually needs via dpkg-shlibdeps, confirms every declared dep exists in apt, and clean-container installs when a docker CLI is available. Both artifacts join the run artifact and the tagged release; install.sh grows a pacman branch so Arch/CachyOS gets a native install instead of the AppImage fallback. Still no release cut (rule 2). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SreJkbxB4gx8pPsu8QbLPi
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
# Maintainer: bvandeusen
|
||||
#
|
||||
# ThoughtSync desktop (Tauri v2) — native Arch package.
|
||||
#
|
||||
# Built from THIS repo checkout, from SOURCE, linked against your SYSTEM libraries.
|
||||
# That is the whole point: it uses the host's graphics stack (webkit2gtk-4.1 + your
|
||||
# GPU driver), which avoids the bundled-AppImage "EGL_BAD_PARAMETER" black window.
|
||||
#
|
||||
# Usage (from a clone of the thoughtsync repo):
|
||||
# cd desktop/packaging/arch
|
||||
# makepkg -si
|
||||
#
|
||||
pkgname=thoughtsync-desktop
|
||||
pkgver=0.1.0
|
||||
pkgrel=1
|
||||
pkgdesc="ThoughtSync desktop — local-first Keep-style thought capture"
|
||||
arch=('x86_64')
|
||||
url="https://git.fabledsword.com/bvandeusen/thoughtsync"
|
||||
license=('MIT')
|
||||
depends=(
|
||||
'webkit2gtk-4.1'
|
||||
'gtk3'
|
||||
'cairo'
|
||||
'gdk-pixbuf2'
|
||||
'glib2'
|
||||
'libsoup3'
|
||||
'pango'
|
||||
'hicolor-icon-theme'
|
||||
'desktop-file-utils'
|
||||
'librsvg'
|
||||
)
|
||||
makedepends=('rust' 'nodejs' 'npm' 'git' 'pkgconf')
|
||||
# Cargo's release profile already does its own LTO; don't let makepkg inject C-level
|
||||
# LTO flags into the crates that build native code.
|
||||
options=('!lto')
|
||||
|
||||
# Locate the repo root this PKGBUILD lives inside (desktop/packaging/arch/).
|
||||
_repo() { git -C "$startdir" rev-parse --show-toplevel; }
|
||||
|
||||
pkgver() {
|
||||
cd "$startdir"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
build() {
|
||||
local repo; repo="$(_repo)"
|
||||
|
||||
# 1) Build the shared Vue frontend — it's embedded into the binary at compile time
|
||||
# (tauri generate_context!), so it must exist before the cargo build.
|
||||
cd "$repo/frontend"
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
# 2) Compile the native binary against SYSTEM libraries (no bundling, no tauri-cli).
|
||||
cd "$repo/desktop/src-tauri"
|
||||
cargo build --release
|
||||
}
|
||||
|
||||
package() {
|
||||
local repo; repo="$(_repo)"
|
||||
|
||||
install -Dm755 "$repo/desktop/src-tauri/target/release/thoughtsync-desktop" \
|
||||
"$pkgdir/usr/bin/thoughtsync"
|
||||
install -Dm644 "$repo/desktop/src-tauri/app-icon.png" \
|
||||
"$pkgdir/usr/share/pixmaps/thoughtsync.png"
|
||||
install -Dm644 "$startdir/thoughtsync.desktop" \
|
||||
"$pkgdir/usr/share/applications/thoughtsync.desktop"
|
||||
}
|
||||
@@ -1,31 +1,60 @@
|
||||
# ThoughtSync desktop — Arch package
|
||||
|
||||
A native Arch/pacman package, built **from source** so it links against your
|
||||
**system** libraries (webkit2gtk-4.1 + your GPU driver). This is the robust install
|
||||
on Arch/CachyOS: it avoids the bundled-AppImage `EGL_BAD_PARAMETER` black-window
|
||||
problem entirely, and it installs a proper application-menu entry.
|
||||
A **prebuilt** native pacman package (`.pkg.tar.zst`), published as an asset on
|
||||
every ThoughtSync release. Nothing to compile, no toolchain to install.
|
||||
|
||||
Installing natively on Arch matters for more than tidiness: pacman pulls
|
||||
`webkit2gtk-4.1` itself and the app runs against your system's graphics stack,
|
||||
which is what keeps the bundled-library `EGL_BAD_PARAMETER` black window
|
||||
(issue 2021) from coming back. It also means the app is package-manager tracked
|
||||
and uninstalls cleanly.
|
||||
|
||||
## Install
|
||||
|
||||
From a clone of the `thoughtsync` repo:
|
||||
Easiest — the one-command installer picks this package automatically on any
|
||||
pacman system:
|
||||
|
||||
```sh
|
||||
cd desktop/packaging/arch
|
||||
makepkg -si
|
||||
curl -fsSL https://git.fabledsword.com/bvandeusen/thoughtsync/raw/branch/main/desktop/packaging/install.sh | sh
|
||||
```
|
||||
|
||||
`makepkg` will pull the build tools (`rust`, `nodejs`, `npm`) and runtime deps
|
||||
(`webkit2gtk-4.1`, `gtk3`, …) via pacman, compile the frontend + the Rust binary,
|
||||
and install:
|
||||
Or grab the `.pkg.tar.zst` from the
|
||||
[latest release](https://git.fabledsword.com/bvandeusen/thoughtsync/releases/latest)
|
||||
and install it directly:
|
||||
|
||||
```sh
|
||||
sudo pacman -U thoughtsync-desktop-*-x86_64.pkg.tar.zst
|
||||
```
|
||||
|
||||
Either way you get:
|
||||
|
||||
- `/usr/bin/thoughtsync` — the app
|
||||
- `/usr/share/applications/thoughtsync.desktop` — the menu entry
|
||||
- `/usr/share/pixmaps/thoughtsync.png` — the icon
|
||||
- `/usr/share/icons/hicolor/*/apps/thoughtsync.png` — themed icons
|
||||
|
||||
Then launch **ThoughtSync** from your app menu (or run `thoughtsync`).
|
||||
Launch **ThoughtSync** from your app menu, or run `thoughtsync`.
|
||||
|
||||
## Notes
|
||||
Uninstall: `sudo pacman -R thoughtsync-desktop`.
|
||||
|
||||
- Builds in-place from the checkout (`makepkg` reads the committed state via git).
|
||||
- The compile takes a few minutes the first time (Rust release build).
|
||||
- Uninstall: `sudo pacman -R thoughtsync-desktop`.
|
||||
## How the package is built
|
||||
|
||||
`package-prebuilt.sh` runs in CI (`.forgejo/workflows/desktop.yml`) and wraps the
|
||||
binary the Linux build already produced into a pacman package — it does not
|
||||
compile anything a second time.
|
||||
|
||||
Packaging a Debian-compiled binary for Arch is safe here because the binary
|
||||
bundles nothing: it resolves `libwebkit2gtk-4.1.so.0`, `libgtk-3.so.0` and
|
||||
`libsoup-3.0.so.0` by SONAME at runtime and those are identical on both distros,
|
||||
SQLite is compiled in (`rusqlite` "bundled"), and glibc's forward compatibility
|
||||
means building on Debian's older glibc and running on Arch's newer one is the
|
||||
safe direction.
|
||||
|
||||
CI is Debian and has no `pacman`, so it cannot install-test the result. The build
|
||||
step instead logs the package's `.PKGINFO` and complete file listing, so the
|
||||
package is auditable from the run log; a real `pacman -U` is the final proof.
|
||||
|
||||
## Previously
|
||||
|
||||
This directory used to hold a source-build `PKGBUILD` requiring `makepkg -si`
|
||||
with `rust` + `nodejs` + `npm` installed. It was removed once prebuilt packages
|
||||
shipped — asking every user to install a compiler toolchain isn't distribution.
|
||||
|
||||
Executable
+155
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build a PREBUILT Arch package (.pkg.tar.zst) from the binary the desktop CI job
|
||||
# already compiled — no makepkg, no Arch container, no second Rust build.
|
||||
#
|
||||
# WHY prebuilt: the source PKGBUILD this replaces required every user to install
|
||||
# rust + nodejs + npm and compile for minutes before they could open the app.
|
||||
# Distribution means shipping a package people can just install, so the one-command
|
||||
# installer (install.sh) can `pacman -U` a real native package on Arch/CachyOS
|
||||
# instead of falling back to the AppImage.
|
||||
#
|
||||
# WHY it's safe to package a Debian-compiled binary for Arch: the binary bundles
|
||||
# nothing. It resolves libwebkit2gtk-4.1.so.0 / libgtk-3.so.0 / libsoup-3.0.so.0 by
|
||||
# SONAME at runtime, and those sonames are identical on both distros; SQLite is
|
||||
# compiled in (rusqlite "bundled"). glibc symbol versioning is forward-compatible,
|
||||
# and we build on Debian's older glibc and run on Arch's newer one — the safe
|
||||
# direction. Using the host's graphics stack is also exactly what keeps issue 2021
|
||||
# (bundled-lib EGL_BAD_PARAMETER black window) fixed.
|
||||
#
|
||||
# A .pkg.tar.* is just a tar whose FIRST entry is .PKGINFO, so we assemble it
|
||||
# directly rather than nesting an Arch container over the docker socket.
|
||||
#
|
||||
# CI cannot verify this end-to-end: the runner is Debian and has no pacman. The
|
||||
# step logs .PKGINFO and the full file listing so the package is auditable from the
|
||||
# build log; `pacman -U` on a real Arch box is the final proof.
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
|
||||
SRC_TAURI="$REPO_ROOT/desktop/src-tauri"
|
||||
BINARY="$SRC_TAURI/target/release/thoughtsync-desktop"
|
||||
OUT_DIR="${1:-$SRC_TAURI/target/release/bundle/arch}"
|
||||
|
||||
PKGNAME="thoughtsync-desktop"
|
||||
PKGREL=1
|
||||
PKGDESC="ThoughtSync desktop — local-first Keep-style thought capture"
|
||||
URL="https://git.fabledsword.com/bvandeusen/thoughtsync"
|
||||
LICENSE="MIT"
|
||||
PACKAGER="ThoughtSync CI <noreply@fabledsword.com>"
|
||||
|
||||
# Runtime deps. Deliberately minimal and grounded in what the binary actually
|
||||
# links: tauri is built with features=[] (no tray -> no libayatana-appindicator)
|
||||
# and rusqlite is "bundled" (no sqlite package). Everything else — glib2, cairo,
|
||||
# pango, gdk-pixbuf2, libsoup3 — arrives transitively via these two, so listing
|
||||
# them would just be noise that can drift out of date.
|
||||
DEPENDS=(webkit2gtk-4.1 gtk3)
|
||||
|
||||
[ -f "$BINARY" ] || {
|
||||
echo "ERROR: no binary at $BINARY — run the tauri/cargo build first." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Single source of truth for the version: the same tauri.conf.json value the
|
||||
# .deb and the AppImage are stamped with, so all three artifacts on a release
|
||||
# always agree. Plain grep — jq is not guaranteed in the CI image.
|
||||
# `|| true` so a miss falls through to the explicit error below rather than
|
||||
# aborting on pipefail with no explanation.
|
||||
PKGVER="$(grep -oE '"version"[[:space:]]*:[[:space:]]*"[^"]+"' "$SRC_TAURI/tauri.conf.json" |
|
||||
head -1 | sed -E 's/.*"([^"]+)"$/\1/' || true)"
|
||||
[ -n "$PKGVER" ] || { echo "ERROR: could not read version from tauri.conf.json" >&2; exit 1; }
|
||||
|
||||
# Reproducible-ish: prefer the commit date over "now" so rebuilding the same
|
||||
# commit produces the same builddate.
|
||||
BUILDDATE="$(git -C "$REPO_ROOT" log -1 --format=%ct 2>/dev/null || date +%s)"
|
||||
|
||||
echo "==> Packaging $PKGNAME $PKGVER-$PKGREL (x86_64) for pacman"
|
||||
|
||||
STAGE="$(mktemp -d)"
|
||||
trap 'rm -rf "$STAGE"' EXIT INT TERM
|
||||
|
||||
# --- lay out the filesystem tree --------------------------------------------
|
||||
# /usr/bin/thoughtsync (not thoughtsync-desktop): matches the CLI name the
|
||||
# AppImage installer symlinks into ~/.local/bin, so the command is the same
|
||||
# whichever way the app was installed.
|
||||
install -Dm755 "$BINARY" "$STAGE/usr/bin/thoughtsync"
|
||||
install -Dm644 "$SCRIPT_DIR/thoughtsync.desktop" \
|
||||
"$STAGE/usr/share/applications/thoughtsync.desktop"
|
||||
|
||||
# Themed icons, so the menu entry's `Icon=thoughtsync` resolves at every size the
|
||||
# desktop asks for; pixmaps is the legacy fallback for older launchers.
|
||||
install -Dm644 "$SRC_TAURI/icons/32x32.png" \
|
||||
"$STAGE/usr/share/icons/hicolor/32x32/apps/thoughtsync.png"
|
||||
install -Dm644 "$SRC_TAURI/icons/128x128.png" \
|
||||
"$STAGE/usr/share/icons/hicolor/128x128/apps/thoughtsync.png"
|
||||
install -Dm644 "$SRC_TAURI/icons/128x128@2x.png" \
|
||||
"$STAGE/usr/share/icons/hicolor/256x256/apps/thoughtsync.png"
|
||||
install -Dm644 "$SRC_TAURI/icons/icon.png" \
|
||||
"$STAGE/usr/share/icons/hicolor/512x512/apps/thoughtsync.png"
|
||||
install -Dm644 "$SRC_TAURI/icons/icon.png" "$STAGE/usr/share/pixmaps/thoughtsync.png"
|
||||
|
||||
# Installed size in KiB, as pacman reports it.
|
||||
INSTALLED_SIZE="$(du -sb "$STAGE" | cut -f1)"
|
||||
|
||||
# --- .PKGINFO ---------------------------------------------------------------
|
||||
{
|
||||
echo "# Generated by desktop/packaging/arch/package-prebuilt.sh"
|
||||
echo "pkgname = $PKGNAME"
|
||||
echo "pkgbase = $PKGNAME"
|
||||
echo "pkgver = $PKGVER-$PKGREL"
|
||||
echo "pkgdesc = $PKGDESC"
|
||||
echo "url = $URL"
|
||||
echo "builddate = $BUILDDATE"
|
||||
echo "packager = $PACKAGER"
|
||||
echo "size = $INSTALLED_SIZE"
|
||||
echo "arch = x86_64"
|
||||
echo "license = $LICENSE"
|
||||
for d in "${DEPENDS[@]}"; do echo "depend = $d"; done
|
||||
} >"$STAGE/.PKGINFO"
|
||||
|
||||
# --- .MTREE (optional) ------------------------------------------------------
|
||||
# pacman uses .MTREE for `pacman -Qkk` file verification; it is NOT required to
|
||||
# install, and generating it needs bsdtar (libarchive-tools), which the Debian CI
|
||||
# image may not carry. Emit it when we can, skip loudly when we can't, rather
|
||||
# than adding an apt install to the job (rule 5: the image is the toolchain).
|
||||
MTREE_ENTRY=()
|
||||
if command -v bsdtar >/dev/null 2>&1; then
|
||||
( cd "$STAGE" && LANG=C bsdtar -czf .MTREE --format=mtree \
|
||||
--options='!all,use-set,type,uid,gid,mode,time,size,md5,sha256,link' \
|
||||
.PKGINFO usr )
|
||||
MTREE_ENTRY=(.MTREE)
|
||||
echo " .MTREE generated (bsdtar present)"
|
||||
else
|
||||
echo " NOTE: bsdtar absent — packaging without .MTREE."
|
||||
echo " pacman installs this fine; only 'pacman -Qkk' file verification is degraded."
|
||||
fi
|
||||
|
||||
# --- compress ---------------------------------------------------------------
|
||||
# pacman reads whatever libarchive can decompress, so degrade gracefully instead
|
||||
# of hard-requiring zstd in the build image. zstd is the modern default.
|
||||
if command -v zstd >/dev/null 2>&1; then
|
||||
COMP_EXT="zst"; COMP_CMD=(zstd -c -T0 -19 -)
|
||||
elif command -v xz >/dev/null 2>&1; then
|
||||
COMP_EXT="xz"; COMP_CMD=(xz -c -T0 -)
|
||||
else
|
||||
COMP_EXT="gz"; COMP_CMD=(gzip -c -)
|
||||
fi
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
PKGFILE="$OUT_DIR/$PKGNAME-$PKGVER-$PKGREL-x86_64.pkg.tar.$COMP_EXT"
|
||||
|
||||
# .PKGINFO MUST be the first entry in the archive — pacman reads it as a stream
|
||||
# and gives up if the metadata isn't up front. Listing it first is what guarantees
|
||||
# that ordering; `usr` is appended after.
|
||||
TAR=tar
|
||||
command -v bsdtar >/dev/null 2>&1 && TAR=bsdtar
|
||||
( cd "$STAGE" && "$TAR" -cf - .PKGINFO "${MTREE_ENTRY[@]}" usr ) | "${COMP_CMD[@]}" >"$PKGFILE"
|
||||
|
||||
# --- report (the CI log IS the audit trail — see header) --------------------
|
||||
echo "==> Built $(basename "$PKGFILE") ($(du -h "$PKGFILE" | cut -f1), compression: $COMP_EXT)"
|
||||
echo "--- .PKGINFO ---"
|
||||
sed 's/^/ /' "$STAGE/.PKGINFO"
|
||||
echo "--- contents ---"
|
||||
"$TAR" -tf "$PKGFILE" | sed 's/^/ /'
|
||||
echo "==> Install on Arch with: sudo pacman -U $(basename "$PKGFILE")"
|
||||
Reference in New Issue
Block a user