fix(desktop): stage and verify AppImage replacements#21621

open1
main
desktop-app-12/appimage-replacement
opened10d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 47m ago

A failed cross-filesystem AppImage update can remove the installed executable before the downloaded replacement finishes copying. Stage the replacement beside its destination, verify release size and SHA-512, set executable permissions, sync it, and commit with one rename. Cleanup runs after the commit and preserves aliases of the installed file.

This is the file-replacement layer rebuilt from @MarMarLabs's #20117. The dependent layer activates it in electron-updater. The original identified the failure correctly; the rebuild keeps its verified staging behavior and drops the separate shutdown/telemetry drain work.

Stack: #21622 is the dependent integration layer.

Verification:

  • This layer: 15 passing tests in the existing ElectronUpdater.test.ts (5 existing + 10 behavioral cases). Removing SHA verification makes the corruption regression fail.
  • The complete stack: 22 passing updater tests, plus 43 passing existing desktop update/lifecycle tests; desktop typecheck, scoped lint, and formatting pass.
  • Real Linux mount-namespace proof uses the actual AppImageUpdater.install with 40 MiB executable fixtures, separate tmpfs filesystems, and real ENOSPC. Stock updater leaves a 24 MiB partial executable that cannot run; the rebuilt stack keeps the runnable 40 MiB old executable and complete download. A separate real bind-mounted cache test verifies that cleanup preserves the committed executable.
text
1cross-filesystem ENOSPC: stock installedBytes=25165824 oldAppRuns=false
2cross-filesystem ENOSPC: rebuilt installedBytes=41943040 oldAppRuns=true
3bind-mounted cache alias: rebuilt newAppRuns=true destinationSurvivesCleanup=true

The live fixtures are shell executables, not packaged Electron/FUSE AppImages. Packaged Linux success/failure, real Electron shutdown/relaunch and single-instance locking still need human qualification before landing. macOS, Windows, iOS, Android and Electron desktop UI were not exercised. This nonvisual filesystem change has test/CLI evidence instead of screenshots.

Staging always copies the download so a later verification, sync, or final-rename failure leaves the cached download available. This requires another AppImage-sized allocation even on one filesystem, and copy/hash/sync run synchronously during installation. Rename-first staging would need rollback handling to preserve a valid cache after later failures; that optimization is outside this repair.

Two independent full-stack review rounds (Claude Opus 5.5 and GPT-6-Sol) found no remaining code defects. The full-copy allocation/I/O cost is accepted and documented; packaged qualification remains a landing gate.

Implementation and tests: GPT-6.1-Sol and GPT-6-Astra through Codex in T3 Code; independent review: Claude Opus 5.5 and GPT-6-Sol in T3 Code.

Closes #10685

Checks

22 successful · 9 skipped · 1 neutral
All checks passed
4e41d35

Added 1 commit

  • fix(desktop): stage and verify AppImage replacements4e41d35
Synced from GitHub

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — The PR introduces a production AppImage replacement layer with synchronous staging, verification, permission changes, atomic renaming, and cleanup, alongside extensive filesystem tests. It also adds directives that suppress the nodeBuiltinImport static-analysis diagnostic, so the change requires human review.

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

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Team
  • Run ID: 16ddb10d-fe34-4d58-ad96-234a811ad3bc
📥 Commits

Reviewing files that changed from the base of the PR and between 1451e7cb23034d29774338608368a15d8845df36 and 4e41d353b0eb7b5096d064a9323521146d382d1a.

📒 Files selected for processing: 2
  • apps/desktop/src/electron/AppImageInstall.ts
  • apps/desktop/src/electron/ElectronUpdater.test.ts

Limit details: You’ve used all 10 included reviews currently available.

📝 Walkthrough

The pull request adds installAppImageUpdate to install downloaded AppImages through a staged, verified replacement. It also adds tests for successful replacement, invalid installers, filesystem failures, and cache-path cleanup.

Changes: AppImage Update Installation

Layer / File(s)Summary
Verified AppImage replacement
apps/desktop/src/electron/AppImageInstall.ts, apps/desktop/src/electron/ElectronUpdater.test.ts
installAppImageUpdate validates and stages the installer, verifies its size and SHA-512 digest, sets executable permissions, and renames it to the destination. Tests cover generic and versioned destinations, pre-commit failures, path aliases, and post-commit cleanup failures.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

mermaid
1sequenceDiagram
2 participant Updater
3 participant installAppImageUpdate
4 participant StagingFile
5 participant Destination
6 Updater->>installAppImageUpdate: pass installer path and expected digest
7 installAppImageUpdate->>StagingFile: copy, verify, set permissions, and sync
8 installAppImageUpdate->>Destination: rename staged file into place
9 installAppImageUpdate->>StagingFile: remove staging directory
Merge Risk: ⚪ Minimal · up to 4e41d

No actionable defect is established in this replacement layer; complete the planned packaged Linux qualification before release.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title is concise, specific, and accurately describes the main change: staging and verifying AppImage replacements.
Description checkPassedThe description clearly explains the problem, implementation, scope, verification results, limitations, and related issues. It does not use the template headings and does not explicitly identify a mai…
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description clearly explains the problem, implementation, scope, verification results, limitations, and related issues. It does not use the template headings and does not explicitly identify a maintainer approval comment, but it provides substantial scope and issue context, so the description is mostly complete.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Usage-based review receipt

Note

This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.

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