It read the version straight out of tauri.conf.json, which was correct until dev builds started overriding the version on the command line — the file still says 0.1.0, so release `dev` came out carrying a pacman package labelled 0.1.0 around a binary that reports 0.1.132. Nothing breaks from it (a pacman install can't self-update anyway), but a package that lies about its version is exactly what makes a later "which build is this?" impossible to answer. Now uses the same build-version.sh the bundles and the manifest do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SreJkbxB4gx8pPsu8QbLPi
159 lines
7.2 KiB
Bash
Executable File
159 lines
7.2 KiB
Bash
Executable File
#!/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 helper the bundle build uses.
|
|
#
|
|
# It used to read tauri.conf.json directly, which was right until dev builds began
|
|
# overriding the version on the command line (M10.9) — the file still says 0.1.0, so
|
|
# the pacman package came out stamped 0.1.0 around a binary reporting 0.1.132. A
|
|
# package that lies about its version is exactly what makes a later "which build is
|
|
# this?" question unanswerable.
|
|
# `|| true` so a miss falls through to the explicit error below rather than
|
|
# aborting on pipefail with no explanation.
|
|
PKGVER="$(sh "$SCRIPT_DIR/../build-version.sh" || true)"
|
|
[ -n "$PKGVER" ] || { echo "ERROR: could not determine the build version" >&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")"
|