Skip to content

fix(appimage): give the release startup smoke a D-Bus session bus - #5255

Merged
M3gA-Mind merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:fix/appimage-smoke-dbus-session
Jul 28, 2026
Merged

fix(appimage): give the release startup smoke a D-Bus session bus#5255
M3gA-Mind merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:fix/appimage-smoke-dbus-session

Conversation

@M3gA-Mind

Copy link
Copy Markdown
Contributor

Summary

  • Wrap the AppImage startup smoke in dbus-run-session (falling back to dbus-launch) so tauri-plugin-single-instance can initialise in the headless CI environment instead of panicking.
  • Always drop the inherited DBUS_SESSION_BUS_ADDRESS before the smoke, so a poisoned disabled value can never reach the app.
  • Install dbus / dbus-x11 on the ubuntu builders so the wrapper is guaranteed present rather than silently degrading.
  • Detect this specific panic explicitly, and echo the inherited bus address, so a recurrence is self-diagnosing.
  • No Rust change — the existing single-instance guard stays as the runtime safety net.

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 -> 0 and the temporary AppArmor profile loading. The smoke now dies for a different reason, exit 101:

[appimage-runtime]   [ERROR:dbus/bus.cc:405] Failed to connect to the bus:
                     Could not parse server address: Unknown address type
[appimage-runtime]   thread 'main' (60614) panicked at
                     plugins/single-instance/src/platform_impl/linux.rs:57:18:
[appimage-runtime]   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 process down before any window exists.

The libcef.so => not found ldd lines in that job are not the failure. The app reached main() 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.sh starts a bus with dbus-launch when 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:

  1. Echoes the inherited DBUS_SESSION_BUS_ADDRESS before running (see the open question below).
  2. Always unsets it, so even on the no-wrapper path a literal disabled cannot reach the app. With the variable absent, the app's own can_register_single_instance_plugin() probe falls back to inspecting $XDG_RUNTIME_DIR/bus; the string disabled is precisely what zbus refuses to parse.
  3. Wraps AppRun in dbus-run-session --, falling back to dbus-launch --exit-with-session, warning if neither exists. The bus dies with the wrapped command, so no teardown is needed, the 15s timeout still bounds the run, and the required exit-124 contract is unchanged.
  4. Names this failure in the forbidden-pattern check, since it exits 101 like any other Rust panic.

dbus / dbus-x11 are 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, and dbus_address_is_supported("disabled") correctly returns false. I confirmed the guard is present at the failing commit 42cdf77e, not only on main.

Yet its warn line [single-instance] D-Bus session bus unreachable appears nowhere in the 33,503-line run log — so the guard evidently returned true. The only way that happens is DBUS_SESSION_BUS_ADDRESS being unset while $XDG_RUNTIME_DIR/bus exists, but then zbus could never produce the string disabled. 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/bus socket present, then the guard's None => xdg_runtime_bus_socket_exists branch 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

  • Tests added or updated — N/A: CI-only shell/workflow change. The script's fixture test scripts/release/test-strip-appimage-rpaths.sh covers the static-validation path and SKIPs without patchelf; the smoke path itself requires a real Linux AppImage and is exercised by the release job.
  • Diff coverage ≥ 80%N/A: no Vitest/Rust source changed (shell script + workflow YAML only).
  • Coverage matrix updated — N/A: behaviour-only change to a CI validation script.
  • All affected feature IDs listed — N/A: no feature surface touched.
  • No new external network dependencies introduced — no network use added; dbus/dbus-x11 are distro packages installed alongside the existing ubuntu build deps.
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: this changes how the automated smoke runs, not what a human verifies post-release.
  • Linked issue closed via Closes #NNNN/A: no tracking issue; this is a direct fix for the failed run linked above.

Impact

  • Platform: Linux release builds only. Nothing in the shipped artifact changes — the AppImage bytes are identical; only how CI exercises them changes.
  • Verification: validated locally as far as a Mac allows — bash -n clean, and the ${arr[@]+"${arr[@]}"} idiom proven safe under set -euo pipefail on bash 3.2 both empty and filled (a bare "${arr[@]}" breaks on bash < 4.4, which this script's set -u would trip). The Linux AppImage path itself cannot be run here.
  • A maintainer must re-dispatch Release Production to confirm the fix. This PR targets main only; the release branch will need the usual promotion or a cherry-pick once verified.

Related

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
@M3gA-Mind
M3gA-Mind requested a review from a team July 28, 2026 22:28
@M3gA-Mind

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ee298d25-11bd-48dd-811c-0d796e5ec095

📥 Commits

Reviewing files that changed from the base of the PR and between 9750b80 and 0b2520c.

📒 Files selected for processing (2)
  • .github/workflows/build-desktop.yml
  • scripts/release/validate-appimage-runtime.sh

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a CI-only AppImage startup smoke failure on Ubuntu runners by providing a D-Bus session bus before launching the AppImage — mirroring the same fix already applied to the desktop e2e runner. No shipped artifact bytes change; only the CI validation script and the runner's package list are affected.

  • validate-appimage-runtime.sh: Always unsets the inherited DBUS_SESSION_BUS_ADDRESS, wraps AppRun in dbus-run-session (falling back to dbus-launch --exit-with-session), and adds an explicit detection message for the D-Bus panic so future failures self-diagnose rather than misleading investigators toward unrelated libcef.so ldd output.
  • build-desktop.yml: Adds dbus and dbus-x11 to the ubuntu apt install block, guaranteeing that dbus-run-session (primary path) and dbus-launch (fallback) are available on the runner.

Confidence Score: 5/5

Safe to merge; changes are limited to CI infrastructure and do not affect the shipped AppImage artifact.

The fix correctly identifies the root cause, the ${arr[@]+"${arr[@]}"} idiom is the right approach for bash 3.2 under set -u, dbus-run-session execs the child so timeout cleanly captures exit 124, and the dbus-launch fallback behaves equivalently. The new D-Bus panic grep check adds a clearer failure message without changing the exit path. No Rust or product code is touched.

Files Needing Attention: No files require special attention.

Important Files Changed

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]
Loading

Reviews (1): Last reviewed commit: "fix(appimage): give the release startup ..." | Re-trigger Greptile

@M3gA-Mind
M3gA-Mind merged commit 11d744a into tinyhumansai:main Jul 28, 2026
20 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant