fix(appimage): give the release startup smoke a D-Bus session bus - #5255
Conversation
The Release Production ubuntu build fails in the AppImage startup smoke with exit 101. The userns fix (tinyhumansai#5251/tinyhumansai#5252) is working — the log shows the sysctl relaxed 1 -> 0 and the temporary AppArmor profile loaded — but the app now panics for a different reason: thread 'main' panicked at plugins/single-instance/src/platform_impl/linux.rs:57 called `Result::unwrap()` on an `Err` value: Address("unsupported transport 'disabled'") `tauri-plugin-single-instance` calls `zbus::blocking::connection::Builder::session().unwrap()` in its `setup()`, so with no usable session bus it takes the whole process down before any window exists. Chromium logs the same condition as "Failed to connect to the bus: Could not parse server address". The `libcef.so => not found` ldd lines in that job are NOT the failure — the app reached main() and printed its own [cef-startup] logs, so CEF loaded fine. A real desktop user always launches the AppImage inside a session that has a D-Bus session bus; a CI runner does not. `app/scripts/e2e-run-session.sh` already starts one with `dbus-launch` for the desktop e2e runner, and its comment cites this exact panic — the AppImage smoke never got the same treatment. So: - wrap the smoked `AppRun` in `dbus-run-session --`, falling back to `dbus-launch --exit-with-session`, warning when neither is available. The bus dies with the wrapped command, so the 15s `timeout` still bounds the run and the required exit-124 contract is unchanged. - always `env -u DBUS_SESSION_BUS_ADDRESS` first, so a poisoned inherited `disabled` can never reach the app even on the no-wrapper path — with the variable absent the app's own `can_register_single_instance_plugin()` probe falls back to inspecting `$XDG_RUNTIME_DIR/bus`, whereas the literal string `disabled` is precisely what zbus refuses to parse. - echo the inherited value before the run. The app already guards this case (`can_register_single_instance_plugin`, present at the failing commit), yet its "D-Bus session bus unreachable" warn appears nowhere in the failing log — so the guard evidently returned true. Whether the variable arrives as `disabled`, `disabled:` or unset decides which path it takes, and the log gave no way to tell. This line makes the next run answer it. - detect this panic explicitly. It exits 101 like any other Rust panic, and the generic "status 101" message sent the previous investigation to the non-fatal libcef.so lines. Install `dbus`/`dbus-x11` on the ubuntu builders so the wrapper is guaranteed to exist rather than silently degrading to the warning path. No Rust change: the existing single-instance guard stays as the runtime safety net for genuine no-D-Bus environments (WSL2-without-WSLg, minimal containers). Failed run: https://github.com/tinyhumansai/openhuman/actions/runs/30393949588
|
@coderabbitai review |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 16 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
✅ Action performedReview finished.
|
|
| Filename | Overview |
|---|---|
| scripts/release/validate-appimage-runtime.sh | Adds a D-Bus session bus wrapper before AppRun, diagnostic echo of the inherited address, safe empty-array expansion idiom, and a named forbidden-pattern check for the single-instance panic. Logic, signal propagation through the timeout chain, and set -u safety all look correct. |
| .github/workflows/build-desktop.yml | Appends dbus and dbus-x11 to the existing apt install list so both dbus-run-session and the dbus-launch fallback are guaranteed present on the ubuntu runner; one-line change with no other side effects. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[smoke_extracted_apprun] --> B{dbus-run-session\navailable?}
B -- yes --> C["dbus_wrapper=(dbus-run-session -)"]
B -- no --> D{dbus-launch\navailable?}
D -- yes --> E["dbus_wrapper=(dbus-launch --exit-with-session)"]
D -- no --> F["dbus_wrapper=()\nWARNING: no session bus"]
C --> G[unset DBUS_SESSION_BUS_ADDRESS via env -u]
E --> G
F --> G
G --> H["timeout 15s xvfb-run env unset_args dbus_wrapper AppRun"]
H --> I{exit status?}
I -- 124 timeout --> J{forbidden patterns\nin log?}
I -- other --> K[FAIL: unexpected exit]
J -- D-Bus panic pattern --> L[FAIL: single-instance D-Bus panic]
J -- other forbidden strings --> M[FAIL: library/loader error]
J -- none --> N[PASS: app stayed alive 15s]
Reviews (1): Last reviewed commit: "fix(appimage): give the release startup ..." | Re-trigger Greptile
Summary
dbus-run-session(falling back todbus-launch) sotauri-plugin-single-instancecan initialise in the headless CI environment instead of panicking.DBUS_SESSION_BUS_ADDRESSbefore the smoke, so a poisoneddisabledvalue can never reach the app.dbus/dbus-x11on the ubuntu builders so the wrapper is guaranteed present rather than silently degrading.Problem
Release Production fails in Build desktop matrix / Desktop: ubuntu: https://github.com/tinyhumansai/openhuman/actions/runs/30393949588 (branch
release@42cdf77e).The userns fix from #5251 / #5252 is working — the log shows
Relaxed kernel.apparmor_restrict_unprivileged_userns: 1 -> 0and the temporary AppArmor profile loading. The smoke now dies for a different reason, exit 101:tauri-plugin-single-instancecallszbus::blocking::connection::Builder::session().unwrap()in itssetup(), so with no usable session bus it takes the process down before any window exists.The
libcef.so => not foundldd lines in that job are not the failure. The app reachedmain()and printed its own[startup] platform,[cef-profile],[deep-link-ipc]and[cef-startup]logs, so CEF loaded fine. Calling this out because it cost the previous investigation time.Solution
A real desktop user always launches the AppImage inside a session that has a D-Bus session bus; a CI runner does not. This repo already solves the identical problem for the desktop e2e runner —
app/scripts/e2e-run-session.shstarts a bus withdbus-launchwhen the address is empty or matches^disabled, and its comment cites this exact panic. The AppImage smoke simply never got the same treatment.So
smoke_extracted_apprun()now:DBUS_SESSION_BUS_ADDRESSbefore running (see the open question below).disabledcannot reach the app. With the variable absent, the app's owncan_register_single_instance_plugin()probe falls back to inspecting$XDG_RUNTIME_DIR/bus; the stringdisabledis precisely what zbus refuses to parse.AppRunindbus-run-session --, falling back todbus-launch --exit-with-session, warning if neither exists. The bus dies with the wrapped command, so no teardown is needed, the 15stimeoutstill bounds the run, and the required exit-124 contract is unchanged.dbus/dbus-x11are added to the ubuntu apt install so step 3 takes the real path.An open question I could not close, flagged deliberately
The app already guards this case:
can_register_single_instance_plugin()(app/src-tauri/src/lib.rs:2042) skips plugin registration when the bus address is unsupported, anddbus_address_is_supported("disabled")correctly returnsfalse. I confirmed the guard is present at the failing commit42cdf77e, not only onmain.Yet its warn line
[single-instance] D-Bus session bus unreachableappears nowhere in the 33,503-line run log — so the guard evidently returnedtrue. The only way that happens isDBUS_SESSION_BUS_ADDRESSbeing unset while$XDG_RUNTIME_DIR/busexists, but then zbus could never produce the stringdisabled. I could not reconcile those two facts from the logs, and this is a Linux CI AppImage failure that cannot be reproduced on a Mac.This fix therefore does not depend on knowing which it is — it makes the smoke environment correct either way. The new echo line is there so the next run answers the question. If it turns out the variable is unset with a stale
$XDG_RUNTIME_DIR/bussocket present, then the guard'sNone => xdg_runtime_bus_socket_existsbranch is too optimistic (a socket file can exist without a live bus) and should be tightened in a follow-up — but I did not want to speculatively change Rust I cannot compile-check here during a release incident.Submission Checklist
N/A: CI-only shell/workflow change.The script's fixture testscripts/release/test-strip-appimage-rpaths.shcovers the static-validation path andSKIPs withoutpatchelf; the smoke path itself requires a real Linux AppImage and is exercised by the release job.N/A: no Vitest/Rust source changed (shell script + workflow YAML only).N/A: behaviour-only change to a CI validation script.N/A: no feature surface touched.dbus/dbus-x11are distro packages installed alongside the existing ubuntu build deps.N/A: this changes how the automated smoke runs, not what a human verifies post-release.Closes #NNN—N/A: no tracking issue; this is a direct fix for the failed run linked above.Impact
bash -nclean, and the${arr[@]+"${arr[@]}"}idiom proven safe underset -euo pipefailon bash 3.2 both empty and filled (a bare"${arr[@]}"breaks on bash < 4.4, which this script'sset -uwould trip). The Linux AppImage path itself cannot be run here.mainonly; the release branch will need the usual promotion or a cherry-pick once verified.Related
app/scripts/e2e-run-session.sh(dbus-launch for the desktop e2e runner)