Skip to content

feat(electron): add auto-update functionality with electron-updater - #221

Merged
diegosouzapw merged 2 commits into
diegosouzapw:mainfrom
benzntech:feat/electron-auto-update
Mar 6, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:mainfrom
benzntech:feat/electron-auto-update

Conversation

@benzntech

Copy link
Copy Markdown
Contributor

Summary

  • Added electron-updater dependency for auto-update support
  • Configured GitHub publish settings in electron-builder config
  • Implemented auto-updater event handlers in main.js
  • Added IPC handlers for check/download/install updates
  • Added "Check for Updates" option to system tray menu
  • Exposed update APIs in preload.js for renderer access
  • Auto-checks for updates 3 seconds after app startup (silent mode)
  • Shows desktop notification when update is ready to install

Changes

  • electron/package.json: Added electron-updater dependency and GitHub publish config
  • electron/main.js: Auto-updater setup, IPC handlers, tray menu integration
  • electron/preload.js: Exposed checkForUpdates, downloadUpdate, installUpdate, onUpdateStatus APIs

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces robust auto-update capabilities to the Electron application, significantly enhancing the user experience by ensuring that users always have the latest version without manual intervention. It streamlines the update process from checking and downloading to installation, complete with user notifications and integration into the application's system tray.

Highlights

  • Auto-Update Functionality: Integrated electron-updater to enable automatic updates for the application.
  • Configuration: Configured GitHub publish settings within the electron-builder configuration for update distribution.
  • Main Process Logic: Implemented auto-updater event handlers, IPC handlers for update actions (check, download, install), and integrated a 'Check for Updates' option into the system tray menu in main.js.
  • Renderer Process Access: Exposed update-related APIs in preload.js to allow the renderer process to interact with the auto-updater.
  • Automatic Check: The application now silently checks for updates 3 seconds after startup.
  • User Notification: Users will receive a desktop notification when an update is ready to be installed.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • electron/main.js
    • Imported dialog, Notification, and autoUpdater.
    • Configured autoUpdater behavior (e.g., autoDownload, autoInstallOnAppQuit).
    • Implemented setupAutoUpdater function to handle various update events (checking, available, downloaded, error).
    • Added checkForUpdates, downloadUpdate, and installUpdate functions.
    • Integrated a 'Check for Updates' option into the system tray menu.
    • Added IPC handlers for update actions and retrieving the app version.
    • Initialized setupAutoUpdater and scheduled a silent update check on app startup.
  • electron/package.json
    • Added electron-updater dependency.
    • Configured GitHub publish settings for electron-builder.
  • electron/preload.js
    • Expanded VALID_CHANNELS.invoke to include new IPC channels for update operations and app version retrieval.
    • Added update-status to VALID_CHANNELS.receive.
    • Exposed getAppVersion, checkForUpdates, downloadUpdate, installUpdate, and onUpdateStatus to the renderer process via contextBridge.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

Comment thread electron/main.js Outdated
nativeImage,
shell,
session,
dialog,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Unused import - dialog is imported but never used in the codebase. Either remove this import or implement dialog functionality.

Comment thread electron/main.js
// ── Auto-Updater Configuration ──────────────────────────────
autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = true;
autoUpdater.logger = console;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Using console as the logger could expose sensitive information in production. Consider using a proper logger or setting up environment-specific logging levels.

Comment thread electron/main.js
body: `Version ${info.version} is ready to install. Click to restart.`,
});
notification.on("click", () => {
autoUpdater.quitAndInstall();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: quitAndInstall() is called without any cleanup of the Next.js server or saving application state. This could lead to data loss or incomplete operations. Consider graceful shutdown before installing updates.

Comment thread electron/main.js
return { success: true };
});

ipcMain.handle("get-app-version", () => app.getVersion());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: The get-app-version handler doesn't return the version. It calls app.getVersion() but doesn't return the result, so callers will always receive undefined instead of the actual version string.

Comment thread electron/main.js Outdated
// Auto-update IPC handlers
ipcMain.handle("check-for-updates", async () => {
await checkForUpdates(false);
return { success: true };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: This IPC handler returns { success: true } regardless of whether the update check actually succeeded or failed. The renderer process cannot distinguish between success and failure. Consider returning error information when the update check fails.

Comment thread electron/main.js Outdated

ipcMain.handle("download-update", async () => {
await downloadUpdate();
return { success: true };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: This IPC handler returns { success: true } even if downloadUpdate() throws an error. The error is logged but not returned to the caller, making it impossible for the renderer to know if the download failed.

Comment thread electron/main.js Outdated

ipcMain.handle("install-update", () => {
installUpdate();
return { success: true };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: This IPC handler returns { success: true } even though installUpdate() (quitAndInstall) will quit the application immediately. The return value is meaningless in this context.

@kilo-code-bot

kilo-code-bot Bot commented Mar 6, 2026 •

Copy link
Copy Markdown

Code Review Summary

Status: 11 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 7
SUGGESTION 1
MEDIUM 2
Issue Details (click to expand)

CRITICAL

File Line Issue
electron/main.js 506 get-app-version handler doesn't return the version - callers receive undefined

WARNING

File Line Issue
electron/main.js 29 Unused dialog import - imported but never used
electron/main.js 149 No server cleanup before quitAndInstall() - could cause data loss
electron/main.js ~490 Returns { success: true } regardless of actual outcome - renderer can't distinguish success/failure
electron/main.js ~495 Returns { success: true } even when downloadUpdate() throws an error
electron/main.js ~500 Returns { success: true } before quitAndInstall() quits the app - meaningless return value
electron/main.js ~173 checkForUpdates() catches errors but doesn't re-throw - prevents IPC handler from rejecting
electron/main.js ~185 downloadUpdate() catches errors but doesn't re-throw - prevents IPC handler from rejecting

SUGGESTION

File Line Issue
electron/main.js 70 Using console as logger could expose sensitive information in production

MEDIUM

File Line Issue
electron/main.js 70 Consider using electron-log instead of console for better production logging
electron/package.json 37 Hardcoded owner and repo in publish config - consider using repository field instead
Other Observations (not in diff)

No additional issues found in unchanged code.

Files Reviewed (3 files)
  • electron/main.js - 10 issues
  • electron/package.json - 1 issue
  • electron/preload.js - No issues (properly exposes new APIs via contextBridge)

Fix Link: Fix these issues in Kilo Cloud

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a solid foundation for auto-updates using electron-updater. The implementation in the main process is well-structured, covering event handling, IPC communication, and user notifications. My feedback includes suggestions to improve error propagation for IPC handlers and align with best practices for configuration and logging. A key point to consider is that the feature appears incomplete on the renderer side; the new APIs exposed in preload.js are not yet consumed by any frontend hooks or components, and the TypeScript definitions have not been updated. This will need to be addressed for the feature to be fully functional.

Comment thread electron/main.js Outdated
Comment on lines +173 to +176
console.error("[Electron] Check for updates failed:", error);
if (!silent) {
sendToRenderer("update-status", { status: "error", message: error.message });
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This catch block currently handles the error by logging it and sending an IPC message, but it effectively swallows the error. This prevents the promise returned by ipcMain.handle from rejecting, which can be misleading for the renderer process. To ensure the renderer can properly handle failures (e.g., in a try/catch block around the invoke call), you should re-throw the error after logging it.

    console.error("[Electron] Check for updates failed:", error);
    if (!silent) {
      sendToRenderer("update-status", { status: "error", message: error.message });
    }
    throw error;

Comment thread electron/main.js Outdated
Comment on lines +184 to +185
console.error("[Electron] Download update failed:", error);
sendToRenderer("update-status", { status: "error", message: error.message });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the checkForUpdates function, this catch block swallows the error. This prevents the corresponding ipcMain.handle from rejecting on failure. You should re-throw the error here as well to ensure the renderer process is aware of the failure and can handle it appropriately.

    console.error("[Electron] Download update failed:", error);
    sendToRenderer("update-status", { status: "error", message: error.message });
    throw error;

Comment thread electron/main.js
// ── Auto-Updater Configuration ──────────────────────────────
autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = true;
autoUpdater.logger = console;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While using console for logging is acceptable during development, electron-updater strongly recommends using electron-log in production. It provides out-of-the-box file logging, which is invaluable for diagnosing update-related issues on user machines. You'll need to add electron-log to your dependencies in package.json.

Suggested change
autoUpdater.logger = console;
autoUpdater.logger = require("electron-log");

Comment thread electron/package.json
Comment on lines +33 to +37
"publish": {
"provider": "github",
"owner": "diegosouzapw",
"repo": "OmniRoute"
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Hardcoding the owner and repo here works, but it makes the configuration less portable. A more maintainable approach is to let electron-builder infer these values from a repository field in your package.json. You can remove the owner and repo keys and add a top-level repository field instead:

"repository": {
  "type": "git",
  "url": "https://github.com/diegosouzapw/OmniRoute.git"
}
    "publish": {
      "provider": "github"
    },

- Remove unused dialog import
- Stop Next.js server before quitAndInstall() to prevent data loss
- Propagate errors from checkForUpdates/downloadUpdate to IPC handlers
  so renderer can distinguish success from failure
- Remove meaningless return value from install-update handler
@diegosouzapw
diegosouzapw merged commit e5b5838 into diegosouzapw:main Mar 6, 2026
@diegosouzapw

Copy link
Copy Markdown
Owner

Thanks @benzntech for this great contribution! 🎉 The auto-update functionality is now merged and will be part of the next release. We appreciate your effort in adding this important feature!

diegosouzapw added a commit that referenced this pull request Mar 7, 2026
feat(electron): add auto-update functionality with electron-updater
diegosouzapw added a commit that referenced this pull request Sep 10, 2026
Two more HIGH alerts arrived after the first sweep:

  #220 js-yaml (root package-lock.json)     >= 4.0.0, < 4.3.2
  #219 js-yaml (electron/package-lock.json) >= 4.0.0, < 4.3.2

The root's own js-yaml was already on 5.4.1; the vulnerable copies were the ones
nested under @yarnpkg/parsers, lockfile-lint, xmlbuilder2 (root) and the direct
dependency in electron. All now 4.3.2. Four version lines, nothing else.

#221 smol-toml (HIGH, <= 1.7.0) is NOT closed here. The root is on 1.8.0; the
vulnerable 1.6.1 sits under @openai/codex-security, which pins it as an EXACT
version rather than a range, so `npm update` cannot move it. Bumping
codex-security itself (0.1.24 -> 0.1.26) does not help — 0.1.26 pins the same
1.6.1 — so that bump was reverted rather than carried along for no benefit.

Closing #221 needs an upstream codex-security release or an `overrides` entry,
the same trade already declined for #210/tsup: forcing a transitive pin from
outside is how a build breaks silently. Note that @openai/codex-security is also
the package carrying the unpatched extract-zip (#218), so one upstream release
would likely clear both.
diegosouzapw added a commit that referenced this pull request Sep 10, 2026
Closes #221 (smol-toml, HIGH, DoS via malformed TOML, vulnerable <= 1.7.0).

@openai/codex-security pins smol-toml at 1.6.1 as an EXACT version, so no
`npm update` reaches it. This repo already uses `overrides` as its standard tool
for exactly that situation — the block carries 20+ entries, including the
scoped-by-parent form and the `qs`/`fast-uri`/`ip-address` entries that back
earlier security bumps — so a scoped override is the idiomatic fix here, not a
new mechanism:

    "@openai/codex-security": { "smol-toml": "^1.8.0" }

The nested copy deduplicates to the root's existing 1.8.0, which two other
consumers (the root itself and knip) already run, so the version is proven in
this tree. The whole lockfile diff is the 14 lines of the removed 1.6.1 entry.

Also raised the `@yarnpkg/parsers` js-yaml floor from ^4.3.1 to ^4.3.2, so the
override documents the patched version rather than permitting the vulnerable one
it was written against.

Not fixed, and not fixable by version — verified against the npm registry rather
than trusting the advisory metadata:

  #218 extract-zip — latest published IS 2.0.1, the vulnerable version. Dev
       scope, via @openai/codex-security. No release to move to.
  #214 adm-zip — latest published IS 0.6.0, the top of the vulnerable range
       (>= 0.5.9, <= 0.6.0). RUNTIME scope, via onnxruntime-node's ^0.5.16, and
       the repo already overrides adm-zip to ^0.6.0. No release to move to.

Both need an upstream fix or a decision to replace the dependency; neither is a
lockfile change. adm-zip being runtime rather than dev makes it the one worth
tracking.

#210 esbuild stays open too. A flat `overrides: { esbuild: ^0.28.2 }` in
opencode-plugin-v2 does close it — npm then reports 0 vulnerabilities — but it
requires regenerating that lockfile from scratch: 823 lines, 96 packages moved,
for a LOW dev-only alert, and a major esbuild bump inside tsup cannot be
validated here without a real install of that package. Tried, measured,
reverted. Left for an upstream tsup release.

check:lockfile OK on all lockfiles including the workspace consistency check;
check:tracked-artifacts OK; prettier clean.
diegosouzapw added a commit that referenced this pull request Sep 10, 2026
* chore(deps): drain the Dependabot queue — 7 of 10 alerts

Lockfile-only bumps; no manifest touched, so nothing changes for consumers.

Root package-lock.json:
  hono      4.13.0 -> 4.13.7  (#215 #216 #217, medium, patched 4.13.5)
  csv-parse 7.0.1  -> 7.0.2   (#213, medium)
  joi       18.2.3 -> 18.2.8  (#211 #212, low, patched 18.2.4/18.2.5)

@omniroute/opencode-plugin:
  toml      4.1.1  -> 4.3.0   (#209, HIGH, patched 4.1.2)

@omniroute/opencode-plugin-v2:
  esbuild   0.28.1 -> 0.28.2  (#210, low) — the direct copy only; see below.

The plugin-v2 diff looks large but is one package: esbuild ships 27 platform
binaries, each carrying version + resolved + integrity.

Three alerts stay open, deliberately:

  #218 extract-zip (HIGH) and #214 adm-zip (medium) have NO published patch.
  Both are dev-scope. Closing them needs an upstream release or a decision to
  replace the dependency — neither belongs in a lockfile bump.

  #210 esbuild is only half-closed. `node_modules/esbuild` is on 0.28.2, but
  `tsup` pins `esbuild: ^0.27.0`, so its nested copy stays at 0.27.7 — inside the
  vulnerable range (>= 0.27.3, < 0.28.1). Updating tsup does not move it (8.5.1
  is already current). Forcing it would take an `overrides` entry pushing a major
  of esbuild inside the bundler, which is exactly the change that breaks a build
  silently, for a LOW dev-only alert. Left for an upstream tsup release.

check:lockfile passes on all three, including the workspace lock/manifest
consistency check. check:tracked-artifacts OK.

* chore(deps): bump js-yaml to 4.3.2 (root + electron)

Two more HIGH alerts arrived after the first sweep:

  #220 js-yaml (root package-lock.json)     >= 4.0.0, < 4.3.2
  #219 js-yaml (electron/package-lock.json) >= 4.0.0, < 4.3.2

The root's own js-yaml was already on 5.4.1; the vulnerable copies were the ones
nested under @yarnpkg/parsers, lockfile-lint, xmlbuilder2 (root) and the direct
dependency in electron. All now 4.3.2. Four version lines, nothing else.

#221 smol-toml (HIGH, <= 1.7.0) is NOT closed here. The root is on 1.8.0; the
vulnerable 1.6.1 sits under @openai/codex-security, which pins it as an EXACT
version rather than a range, so `npm update` cannot move it. Bumping
codex-security itself (0.1.24 -> 0.1.26) does not help — 0.1.26 pins the same
1.6.1 — so that bump was reverted rather than carried along for no benefit.

Closing #221 needs an upstream codex-security release or an `overrides` entry,
the same trade already declined for #210/tsup: forcing a transitive pin from
outside is how a build breaks silently. Note that @openai/codex-security is also
the package carrying the unpatched extract-zip (#218), so one upstream release
would likely clear both.

* chore(deps): override smol-toml to 1.8.0 and raise the js-yaml floor

Closes #221 (smol-toml, HIGH, DoS via malformed TOML, vulnerable <= 1.7.0).

@openai/codex-security pins smol-toml at 1.6.1 as an EXACT version, so no
`npm update` reaches it. This repo already uses `overrides` as its standard tool
for exactly that situation — the block carries 20+ entries, including the
scoped-by-parent form and the `qs`/`fast-uri`/`ip-address` entries that back
earlier security bumps — so a scoped override is the idiomatic fix here, not a
new mechanism:

    "@openai/codex-security": { "smol-toml": "^1.8.0" }

The nested copy deduplicates to the root's existing 1.8.0, which two other
consumers (the root itself and knip) already run, so the version is proven in
this tree. The whole lockfile diff is the 14 lines of the removed 1.6.1 entry.

Also raised the `@yarnpkg/parsers` js-yaml floor from ^4.3.1 to ^4.3.2, so the
override documents the patched version rather than permitting the vulnerable one
it was written against.

Not fixed, and not fixable by version — verified against the npm registry rather
than trusting the advisory metadata:

  #218 extract-zip — latest published IS 2.0.1, the vulnerable version. Dev
       scope, via @openai/codex-security. No release to move to.
  #214 adm-zip — latest published IS 0.6.0, the top of the vulnerable range
       (>= 0.5.9, <= 0.6.0). RUNTIME scope, via onnxruntime-node's ^0.5.16, and
       the repo already overrides adm-zip to ^0.6.0. No release to move to.

Both need an upstream fix or a decision to replace the dependency; neither is a
lockfile change. adm-zip being runtime rather than dev makes it the one worth
tracking.

#210 esbuild stays open too. A flat `overrides: { esbuild: ^0.28.2 }` in
opencode-plugin-v2 does close it — npm then reports 0 vulnerabilities — but it
requires regenerating that lockfile from scratch: 823 lines, 96 packages moved,
for a LOW dev-only alert, and a major esbuild bump inside tsup cannot be
validated here without a real install of that package. Tried, measured,
reverted. Left for an upstream tsup release.

check:lockfile OK on all lockfiles including the workspace consistency check;
check:tracked-artifacts OK; prettier clean.
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.

2 participants