Skip to content

fix(desktop): preserve launchers when AppImages switch to versionless names - #30828

Open
voltcrash wants to merge 5 commits into
pingdotgg:mainfrom
voltcrash:fix/appimage-transition-launchers
Open

voltcrash wants to merge 5 commits into
pingdotgg:mainfrom
voltcrash:fix/appimage-transition-launchers

Conversation

@voltcrash

@voltcrash voltcrash commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

The versioned → versionless AppImage update in #25756 still deletes the path used by existing launchers (#8944). A launcher symlink then fails with ENOENT, even though the new executable is installed.

Preserve that removed path as a relative symlink, using electron-updater 6.8.9's synchronous appimage-filename-updated(destination) event after the move and before relaunch. Only bridge to versionless destination names: later updates replace that file in place, so aliases cannot accumulate across versioned nightly releases. The listener exists only during explicit installation and is removed on failure. A symlink failure warns without aborting installation or overwriting an existing path. Release names, AUR packaging and desktop entries are unchanged.

Release ordering matters: this protects an update initiated by a versioned release that already contains this code. Ship it in a versioned bridge release before switching artifact names. It cannot protect the initial unpatched → first-patched update, repair already-broken launchers, or preserve versioned → versioned updates. Landing this together with versionless artifacts does not retroactively protect ordinary existing installs; the bridge needs to run first.

This is a companion transition fix for #25756, submitted under CONTRIBUTING.md's small, focused obvious-bug exception. The native reproduction establishes the missing launch path; no upstream maintainer approval is claimed.

Verification on Linux ARM64 with executable shell fixtures (not packaged AppImages):

  • Real locked AppImageUpdater.doInstall with native filesystem/shell fixtures and an existing launcher symlink. Before the fix, the transition fixture failed with ENOENT; all six final cases pass. The transition now has one representative filename case because architecture and channel do not change the path behavior. They cover executable permissions, forced relaunch ordering, a custom renamed versioned install transitioning and updating in place afterward, custom versionless names, synchronous relaunch failure with re-download/retry, refusal to overwrite a recreated path, and declining versioned → versioned aliases. The new alias-chain guard regression failed before narrowing the handler.
  • vp run check:changed: passed format, lint, both Knip passes, affected desktop/scripts typechecks, and all six regression cases.

Limits: fixtures call the real synchronous installer but replace Electron's deferred quit and detached launch with synchronous shell execution. No packaged Electron/FUSE or desktop-menu click was tested on either architecture. The shell fixtures run natively on ARM64; x64/ARM64 artifact names are exercised as path behavior. Install-on-quit remains disabled. Move failure before the event retains the dependency's destructive behavior (covered separately by #21621/#21622). The retry fixture re-populates the moved download and bypasses BaseUpdater's error dispatch; it does not prove automatic recovery or asynchronous relaunch handling. No rendered UI changed.

Reviewed with review-loop: 2 rounds with Claude Opus 5.5 on high. Reviewer verdict: approved

Created with GPT-6.1 Sol in the Codex harness.

@github-actions github-actions Bot added vouch:unvouched Author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Nov 4, 2026
@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • Resume reviews
  • Trigger review

No actionable comments were generated in the recent review.

Walkthrough

The updater now handles AppImage filename-update events during installation. Linux tests cover launcher paths across stable and versioned updates, including a path recreated during installation.

Changes: AppImage launch-path handling

Layer / File(s) Summary
Handle AppImage filename changes
apps/desktop/src/electron/ElectronUpdater.ts
When APPIMAGE is set, the updater listens for filename-update events and attempts a symlink unless the destination basename contains a version-like pattern. It removes the listener after installation and logs symlink failures as warnings.
Verify launch paths during updates
apps/desktop/src/electron/ElectronUpdater.launchPaths.test.ts
Linux live tests check stable and versioned update paths, removal of the old path between versioned releases, and preservation of a path recreated during installation.

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ElectronUpdater
  participant AppImageUpdater
  participant Filesystem
  ElectronUpdater->>AppImageUpdater: quitAndInstall()
  AppImageUpdater->>ElectronUpdater: appimage-filename-updated(destination)
  ElectronUpdater->>Filesystem: attempt symlink for eligible destination
  ElectronUpdater->>ElectronUpdater: remove listener after installation
Loading

Suggested reviewers: juliusmarminge, wladefant

Merge Risk: Minimal · up to d3f30

This change keeps existing AppImage launchers working when an update switches to a versionless filename. No actionable merge-blocking risk was found. The change does not repair launchers that are already broken or protect updates started from older builds, so a bridge release must ship first.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the main change: AppImage launchers are preserved when AppImages switch to versionless names. The raw summary shows a symlink from the prior versioned launch path to the versionless de…
Description check Passed The description covers the problem, the change, scope, and verification. It cites the related issue and PR, explains the CONTRIBUTING.md small-fix exception, and lists the test environment, limits, an…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: AppImage launchers are preserved when AppImages switch to versionless names. The raw summary shows a symlink from the prior versioned launch path to the versionless destination, which matches the title. The title is specific and follows the conventional commit format used in the repository template.

Full details: Description check

Explanation

The description covers the problem, the change, scope, and verification. It cites the related issue and PR, explains the CONTRIBUTING.md small-fix exception, and lists the test environment, limits, and results in detail. The template asks for a conventional title, a problem section, a change section, a scope section, and a verification section, and the author provides each of them in plain prose instead of the template headings. The description also ends with the model and harness, as the template requests. It is long and dense, but it is substantively complete. The author did not add the explicit section headings from the template, which a reviewer may want. The description also reports verification run on Linux ARM64 only, which the author states openly.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 9863c3b and d3f30ff.

Files selected for processing: 2

  • apps/desktop/src/electron/ElectronUpdater.launchPaths.test.ts
  • apps/desktop/src/electron/ElectronUpdater.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

@macroscopeapp

macroscopeapp Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — The change preserves existing AppImage launch paths with a symlink when updates adopt versionless filenames. It also adds a file-level static-analysis suppression, which requires human review under the configured approval rules.

You can add or adjust custom eligibility rules. Learn more.

@maria-rcks

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified head 50a4cab9cf163fc2311602dfd2c903f14affd33b on linux x64 with real packaged appimages and the native settings > about > download > install > confirm flow.

  • reproduced on github/main (9e85538535): the versioned-to-versionless update installed the new executable, but the existing launcher failed with ENOENT.
  • repeated with the pr: the old versioned path became a relative symlink to T3-Code-x86_64.AppImage. the original launcher opened the updated desktop app with its project and thread data intact.
  • completed a real codex gpt-6.1-sol turn through that launcher. it ran pwd and git rev-parse --short HEAD and returned /home/user/t3code and 50a4cab9cf.
  • installed a later versionless update through the same native ui. both launcher symlinks survived, the launcher still executed, and the installed appimage matched the update artifact's sha256.
  • the six existing ElectronUpdater.test.ts cases passed through blacksmith-testbox. github checks have no failures or pending runs; the rollup includes skipped jobs and a cancelled duplicate native-fingerprint run. no source changes were needed.

these were locally packaged appimages using the supported administrator https update feed, not shell fixtures or a mocked updater. package versions 0.1.8, 0.1.9, and 0.1.10 exercised release ordering; the later payloads repackaged the same pr bundle with --skip-build, so the compiled about-page version remained 0.1.8. the isolated vm used --password-store=basic, an isolated session bus, and a certificate bypass for the local feed.

command transcript with before/after launcher results and artifact hashes

real codex turn in the updated desktop app opened through the preserved launcher

Not verified

public github release delivery, release rollout ordering, arm64, desktop-menu clicks, and failure recovery were not exercised. macos, windows, ios, and android were not exercised; this change runs in the linux appimage installer. this does not repair already-broken launchers or protect an update initiated by an older build without the fix. a versioned bridge release still needs to ship first.

Wladefant

This comment was marked as spam.

@voltcrash
voltcrash force-pushed the fix/appimage-transition-launchers branch from 50a4cab to 487e519 Compare November 7, 2026 12:04
@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Nov 7, 2026
Wladefant

This comment was marked as spam.

@t3dotgg
t3dotgg dismissed stale reviews from Wladefant and Wladefant November 8, 2026 23:29

Dismissed: unsolicited automated review from a blocked account.

@voltcrash
voltcrash force-pushed the fix/appimage-transition-launchers branch from 487e519 to 9863c3b Compare November 13, 2026 02:45
@juliusmarminge juliusmarminge added the takeover:in-progress A takeover lead is working on this PR label Nov 15, 2026
juliusmarminge and others added 2 commits November 15, 2026 00:30
Drop cases that only re-test electron-updater's own behaviour, run the
transition case through the relaunch path so it fails without the fix,
and skip registering the listener when APPIMAGE is unset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@juliusmarminge juliusmarminge added takeover:blocked Takeover blocked; reason in the PR body and removed takeover:in-progress A takeover lead is working on this PR labels Nov 15, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). takeover:blocked Takeover blocked; reason in the PR body vouch:unvouched Author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants