Three Tauri bugs I found by not trusting a green build
TL;DR š§µ Last week I wrote about one Tauri bug. Someone in the comments told me to check the updater manifest, not just the files it points at. That one nudge turned one bug into three, and my pipeline into something I actually trust. Short version: a green build tells you the toolchain didn't crash. That's it. That's the whole lesson. I maintain StackerPulse, a small Rust + Tauri v2 desktop app for Stacker News. If you build for macOS universal, bug 1 will find you eventually. š Bug 1: every binary but the main one gets left behind My app crate has two binaries: the app, and a little secret scanner I ship as a CLI. [[bin]] name = "stacker-pulse" path = "src/main.rs" [[bin]] name = "seedscan-cli" path = "src/seedscan_cli.rs" required-features = ["cli"] Windows: fine. Linux: fine. macOS universal: the build dies at the bundling step. Built application at: .../target/universal-apple-darwin/release/stacker-pulse failed to bundle project: Failed to copy binary from ".../target/universal-apple-darwin/release/seedscan-cli": does not exist Here's my favourite part. Both halves are doing exactly what they should. Where What it does Correct? desktop.rs, universal branch one lipo -create, main binary only ā yes, in isolation get_binaries() returns every [[bin]] with required-features on ā yes the bundler copies every binary from that list ā yes Three correct behaviours, one broken build. The second binary is compiled for both architectures, never merged into the universal output directory, and then politely requested by name. š” Bug density tip: if Windows and Linux are green, this class of bug can hide in your repo for a long time. I only found it because I ship on three platforms from one workflow. š Bug 2: the CI that claps with no hands So I fixed the workflow. Ran it again. Green. š¢ The draft release had CLI archives, checksums, provenance attestations... and not a single installer. Not one. Zero. tauri-action skips the upload when the release id it got is empty, and exits 0 while doing it. No warning, no red step, no "hey, I uploaded nothing". Just a green check and an empty release. with: tagName: ${{ github.ref_name }} releaseName: "StackerPulse ${{ github.ref_name }}" Two lines. Not a Tauri bug in the strict sense, more of a missing alarm on a door that opens silently. šµļø Bug 3: ten platforms in, two MSIs out This is the one I'm actually proud of, and it exists because someone in the comments told me to check the manifest. So I did. I compared latest.json against the files that were really attached. "platforms": { "windows-x86_64": { "url": "..._x64_en-US.msi" }, "windows-x86_64-msi": { "url": "..._x64_ru-RU.msi" }, "windows-x86_64-nsis": { "url": "..._x64-setup.exe" } } Notice the problem? I build two MSIs, one per language: "windows": { "wix": { "language": ["en-US", "ru-RU"] }, "nsis": { "languages": ["English", "Russian"] } } Two MSIs walk in. The manifest has one key per architecture. One MSI walks out. The Russian build overwrote the English one, and windows-x86_64 still points at English, so now two keys for the same architecture disagree about which language they serve. Every installer is present. Every one is signed. Every asset check passes. And a Russian user on an MSI install gets an English app after the update, and probably never mentions it. Nothing is broken and the result is still wrong. That's the failure mode that actually kills you. š§ What the three have in common Each component does something reasonable alone. lipo merges a binary. The action uploads assets. The bundler writes one entry per artifact type. The bug lives in the handover. In what one side assumes the other produced. Which means "did the build succeed" is not a useful question. It's an answer to a question nobody asked. š Seven lines that replaced my optimism None of these checks looks at build status. # 1. the installers exist gh release view "$TAG" --json assets -q '.assets[].name' | sort > actual.txt diff -u expected.txt actual.txt # 2. the manifest points at them for p in windows-x86_64 linux-x86_64 darwin-aarch64 darwin-x86_64; do jq -e --arg p "$p" '.platforms[$p].url and .platforms[$p].signature' latest.json done # 3. and the manifest version matches the tag jq -r '.version' latest.json | grep -qx "${TAG#v}" The real version in the repo also checks that every download link is pinned to the tag. Draft releases hand out untagged-... URLs that die the instant you publish. š The fix, and two ways I almost made it worse A patch for bug 1 appeared before I wrote mine. Reviewing it turned up something neither of us thought about: // desktop.rs let mut features = config_features; features.extend(options.features); Cargo gets both feature lists. get_binaries() filters on one. Enable a binary through build.features in tauri.conf.json and the merged set is smaller than what the bundler will ask for. Their patch fixes my repro and misses the next one. Classic. And my own near-miss: my first plan was to rename the main binary inside the lipo loop, to honour main_binary_name. Then I read rename_app() and discovered it already renames it after lipo. My version would have made fs::rename hunt for a file that no longer existed. Ten minutes of reading the function I was about to duplicate. One broken release avoided. tauri#16488 merges every binary from get_binaries(), config features merged in first, so both sides finally see the same list. š How I verified it I don't own a Mac. So the check runs in CI, on a real runner, against two refs of tauri-cli: tauri-cli result refs/heads/dev build fails, exit 1 š“ refs/pull/16488/head build succeeds, seedscan-cli inside Contents/MacOS/ š¢ A build that "passes" proves nothing. A build that fails without the patch and passes with it proves the patch does what it claims. Everything else is a wish. š What I'd pass on A green build tells you the toolchain didn't crash. It says nothing about whether the artifact is correct, complete, or the thing you meant to ship. The cheap version of catching that is seven lines of jq and gh release view. The expensive version is finding out from a user whose update quietly installed the wrong language, three months later, assuming they bother to tell you at all. StackerPulse is a small Rust and Tauri app for Stacker News, MIT licensed. If you ship Tauri and build macOS universal, go count your binaries.
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to