Add a Linux desktop build target (AppImage, x64) - #1392
Merged
Conversation
Collaborator
|
TY @salemsayed! I will work on getting this merged this week. I think I will probably keep this as an "alpha" (so not mention it on the website). And let a few people test it (including yourself) so that we can iron out kinks. |
Linux is already a supported bb runtime host; this adds the desktop shell packaging for it. The electron-builder config gains a linux block (AppImage, x64, executableName pinned to "bb" since the Linux default derives from the sanitized package name), with desktop:build:linux, dist:linux, package:linux, and start:linux scripts mirroring the mac ones. The desktop-contract platform widens to macos|linux, the shell injects platform/isMac into pure modules, Linux windows use the native frame and a menu without darwin-only roles, the afterPack native-module hook is platform-parameterized, and the packaged smoke test now runs on darwin and linux. Update checks and auto-update stay darwin-only and log a single line on Linux, where no update feed exists yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JyDzQ6R3oZGzpii6UA5vAW
Generalize ensurePackagedMacOsUserShellPath to ensurePackagedUserShellPath: darwin keeps /bin/zsh -ilc, Linux uses $SHELL (fallback /bin/bash) -ilc. AppImages launched from a desktop entry inherit a minimal PATH, and the desktop app's job is spawning agent CLIs from the user's real PATH. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JyDzQ6R3oZGzpii6UA5vAW
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JyDzQ6R3oZGzpii6UA5vAW
SawyerHood
force-pushed
the
linux-appimage
branch
from
August 13, 2026 07:22
5e1cea2 to
2efc127
Compare
Collaborator
|
Tested using WSL and it works great! Merging |
SawyerHood
added a commit
that referenced
this pull request
Aug 13, 2026
…annels (#1501) ## Summary The Linux AppImage target landed in #1392 as packaging only — it deferred CI, the update feed, and the nightly channel. This closes those three gaps, so Linux ships on every stable release, gets a nightly channel, and has a working update stream. ## Work done **Release (`build-desktop.yml`)** — split into `macos`, `linux` (x64 AppImage), and one `publish` job that needs both. **Nightly (`publish-bb-app.yml`)** — the `nightly-desktop` job became `nightly-desktop-macos` + `nightly-desktop-linux` + `nightly-desktop-publish`, same shape. Both platform jobs derive the nightly version from the run ID, so they agree without sharing state. The single publisher is load-bearing. `desktop-latest` and `desktop-nightly` are moving releases whose assets are fully reset on each publish, so two platform jobs publishing independently would delete each other's binaries. Building in parallel and publishing once removes that race. A failure in either platform job stops the publish, so a release can never ship one platform's binaries against the other's stale feed. **Update stream** — each platform gets its own feed file inside the same release tag: | Platform | Artifacts | electron-updater metadata | Version feed | | --- | --- | --- | --- | | macOS | `.dmg`, `.zip` (2 arch) | `latest-mac.yml` | `desktop-version.json` | | Linux | `.AppImage` (x64) | `latest-linux.yml` | `desktop-version-linux.json` | macOS keeps the unsuffixed name deliberately: shipped macOS builds already request it, and renaming would strand every installed app on its current version. The feed contract's `platform` widened from `z.literal("macos")` to an enum, and the file-name mapping lives in `@bb/desktop-contract` so the build script and the app read one source of truth. **Linux updates ungated** in `main.ts`, split into two capabilities rather than one flag: - Version checks run on every Linux install and report new releases. - Self-installing auto-update runs only inside an AppImage (detected via `APPIMAGE`). An extracted directory or a distro package has no single file to replace, so it would fail every download rather than quietly doing nothing. **Channel separation** — nightly Linux builds use `bb-nightly` as the executable name, so stable and nightly can be installed side by side without one shadowing the other on PATH. Linux artifacts are unsigned; only the macOS binaries wait on the Apple signing secrets, since AppImages have no notarization equivalent. ## Testing Verified locally: - `turbo run typecheck test` green for `@bb/desktop` (223 tests), `@bb/desktop-contract` (19), and `@bb/app` typecheck. - Both workflows parse as YAML; job graph and `needs` wiring confirmed. - The new asset-assembly shell helper exercised directly: required globs exit 1 when unmatched, optional ones skip. This matters because an unmatched glob would otherwise reach `gh` as a literal pattern and fail the upload. - The AppImage packaging assumption checked against the installed electron-builder source — `AppImageTarget` dispatches with `isWriteUpdateInfo: true`, and update-info files are written whenever a publish config exists, independent of `--publish`. So `latest-linux.yml` is produced under the existing `--publish never`. Four `@bb/desktop` suites cannot run in the dev worktree because the Electron binary is not installed; they fail identically on pristine `main`. ## Verification `Build Desktop` was dispatched against this branch before merge with `publish=false, release_channel=qa` — safe by construction, since publishing requires `publish=true` **and** `release_channel=stable` **and** a non-prerelease version. [Run 31683115574](https://github.com/get-bb/bb/actions/runs/31683115574) passed all three jobs: - **Linux** — real AppImage build on `ubuntu-22.04`, `latest-linux.yml`, the version-feed generator, and the headless `xvfb` smoke test. The feed step reads `latest-linux.yml` and would have thrown if it were missing, so both it and `desktop-version-linux.json` are confirmed produced. - **macOS** — unchanged path, still green. - **Publish** — planned first, then correctly skipped both downloads and the release step, avoiding ~953 MB of artifact transfer it would never use. Locally: 228 tests plus 19 in `@bb/desktop-contract`, typechecks clean for `@bb/desktop`, `@bb/desktop-contract`, and `@bb/app`. Four `@bb/desktop` suites cannot run in the dev worktree because the Electron binary is not installed; they fail identically on pristine `main`. Still unexercised by any dry run: - **The release mutation.** Force-pushing the moving tag and resetting assets only happens on a real stable publish. The failure mode is recoverable: the immutable `desktop-v<version>` release is created first and refuses to overwrite. - **The nightly desktop path.** Its jobs are gated on `dry_run == false` (pre-existing), so they cannot run from a branch. They are structurally identical to the jobs above; what is nightly-specific — `bb-nightly` as executable name, `nightly-linux.yml`, the nightly icon — is locally testable with `BB_DESKTOP_RELEASE_CHANNEL=nightly pnpm --filter @bb/desktop run dist:linux`. ## Deliberately out of scope The web download surface has no Linux entry — `apps/web/src/landing/site.ts` still exposes only `DOWNLOAD_MACOS_VERSION_FEED_URL`. Nothing is broken, since macOS kept its feed name, but there is no Linux download CTA yet. Also still deferred from #1392: Linux arm64 and AppStream metadata. The `ubuntu-22.04` runner pin is intentional. The AppImage links against the build machine's glibc, so that pin sets the oldest distro that can run a published build. It is the oldest hosted image GitHub offers, and worth revisiting when it is retired. > AGENT GENERATED: by Claude Opus 5 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Linux x64 AppImage build target to
apps/desktop. Linux is already a first-class bb host —bb-appships"os": ["darwin", "linux"],docs/platform-support.mdlists the Linux persistent host as supported, and Ubuntu is the required CI gate — but the desktop shell was macOS-arm64-only. This closes that gap with a deliberately minimal, additive change: packaging only, no CI or release-infrastructure changes.Per CONTRIBUTING I know features normally start as an issue — happy to convert this into one and treat the branch as the linked prototype if you prefer; opening it as a PR so the concrete diff is easy to evaluate.
Work done
linuxblock only (AppImage, x64,executableName: "bb"— the Linux default derives the binary name from the sanitized package name, yielding@bbdesktop). Existingmac/dmg/publish/npmRebuild/filesconfig untouched; the config gatekeeper test keeps all existing assertions and gains Linux ones.desktop:build:linux(--publish never),dist:linux,package:linux,start:linux, mirroring the mac script names; a@bb/desktop#desktop:build:linuxturbo task mirroringdesktop:build.@bb/desktop-contractplatformwidensz.literal("macos")→z.enum(["macos", "linux"])(info.tsonly; the version-feed schema is untouched since no Linux feed exists).platform/isMacare injected into pure modules as required args (matching how@bb/desktopunit tests already run on ubuntu-latest); onlymain.ts/preload.tsreadprocess.platform. Linux windows use the native frame (the renderer already falls back to non-macOS chrome); the menu drops darwin-only roles; DevTools isControl+Shift+I.afterPackhook is platform-parameterized; better-sqlite3 fetches theelectron-v145-linux-x64prebuild (Electron stays pinned at 41.7.0); node-pty compiles at install time via node-gyp (N-API, so ABI-safe under Electron).ensurePackagedMacOsUserShellPath→ensurePackagedUserShellPath; Linux uses$SHELL(fallback/bin/bash)-ilc, so AppImages launched from a desktop entry get the user's real PATH.smoke:packagedis now cross-platform (darwin|linux) via a shared packaged-binary path resolver.apps/desktop/README.md;docs/repository-overview.mdone-liner.Testing
turbo run typecheck testgreen for@bb/desktop(241 tests) and@bb/desktop-contract(17 tests); the first commit is also independently green so the PATH commit can be dropped cleanly.package:linux→ packaged smoke test passes (bridge reportsplatform: "linux");dist:linux→bb-0.37.0-x86_64.AppImagelaunches with the full stack healthy (server, host-daemon, parcel-watcher child under Electron-as-Node, better-sqlite3 Electron prebuild, node-pty).mainon that machine (zlib golden-byte off-by-ones and timing-sensitive UI tests) — environmental, not introduced here.Work still missing (intentionally deferred — your calls)
latest-linux.yml+ AppImage todesktop-latest(the release job force-resets all assets, so a Linux artifact needs coordination there).build-desktop.yml(ubuntu-latest, no signing). A published AppImage should also build against an older glibc baseline than a dev machine.bb NightlyproductName needs an executableName decision).🤖 Generated with Claude Code
https://claude.ai/code/session_01JyDzQ6R3oZGzpii6UA5vAW