From 98b2ede8bdbf317d2f72369460faf81ca3a60389 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Thu, 20 Aug 2026 22:43:34 +0200 Subject: [PATCH] fix(arch): build with custom-protocol so the package can load its own UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PKGBUILD ran a bare `cargo build --release`. Without `--features tauri/custom-protocol` Tauri does not embed the frontend and serves it from devUrl instead, so the package compiled, linked, installed and passed every check — then launched into "Could not connect to localhost: Connection refused". `tauri build` passes that feature for you and the Android build passes it explicitly; this path never did, so the Arch package has never worked. Adds a check() that catches it at build time. It tests for the *assets*, not for the dev URL: devUrl is part of the config blob generate_context!() embeds either way, so grepping for it reports a failure on a correct build. A content-hashed filename from the vite output can only appear if the bundle was embedded — which is also why the fixed binary is ~400 KB larger. Found by installing the package and launching it, which is the only thing that would have found it. --- packaging/arch/PKGBUILD | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index 013af070..c37f768e 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -29,7 +29,45 @@ build() { bun run build # Only the raw binary is needed; packaging is done in package() below so we # control the Arch filesystem layout ourselves rather than via tauri-bundler. - (cd src-tauri && cargo build --release --locked) + # + # 🔴 `tauri/custom-protocol` is not optional. `tauri build` passes it for you; + # a bare `cargo build` does not, and without it Tauri loads the frontend from + # `devUrl` rather than the assets embedded from `frontendDist`. The result + # builds and installs cleanly and then cannot load its own UI. check() guards + # this. + (cd src-tauri && cargo build --release --locked --features tauri/custom-protocol) +} + +check() { + cd "$_srcdir" + + # A Tauri binary built without `custom-protocol` does not embed the frontend; + # it serves it from `devUrl` (http://localhost:1420) instead. It compiles, + # links and installs perfectly, then launches into "Could not connect to + # localhost: Connection refused" — which is what this package did for its + # entire existence, because `tauri build` adds that feature for you and a bare + # `cargo build` does not. + # + # Test for the *assets*, not for the dev URL: `devUrl` is part of the config + # blob that generate_context!() embeds either way, so its presence proves + # nothing. A content-hashed filename from the vite build can only be in the + # binary if the bundle was embedded — the with-feature binary is ~400 KB + # larger for exactly this reason. + local _binary="src-tauri/target/release/jellytau" + local _asset + _asset="$(basename "$(ls -1 build/_app/immutable/entry/*.js | head -n1)")" + + if [ -z "$_asset" ]; then + echo "==> ERROR: no frontend build found — 'bun run build' did not produce build/_app." >&2 + return 1 + fi + + if ! grep -qa "$_asset" "$_binary"; then + echo "==> ERROR: the frontend bundle is not embedded in the binary." >&2 + echo " Build with --features tauri/custom-protocol, or the packaged app" >&2 + echo " will start up unable to load its own UI." >&2 + return 1 + fi } package() {