-
Notifications
You must be signed in to change notification settings - Fork 39
Simplify electron autoupdater #1361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
fb20ea9
00d2e0a
480af77
40392dd
25e43e4
7e129c2
818afd7
23b0e49
bffe603
39dd64e
6b6f372
0730c92
9319504
e846494
5c96446
efc351e
300dda3
7158c99
28a145b
3c8e632
a9133a9
892da7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import { logger } from '@internxt/drive-desktop-core/build/backend'; | ||
| import { app } from 'electron'; | ||
| import { writeFile } from 'node:fs/promises'; | ||
| import { tmpdir } from 'node:os'; | ||
| import { join } from 'node:path'; | ||
| import { measurePerfomance } from '@/core/utils/measure-performance'; | ||
| import { INTERNXT_VERSION } from '@/core/utils/utils'; | ||
| import { showDialog } from './show-dialog'; | ||
| import { verifyHash } from './verify-hash'; | ||
|
|
||
| export function isNewer(current: string, latestVersion: string) { | ||
| const [la, lb, lc] = latestVersion.split('.').map(Number); | ||
| const [ca, cb, cc] = current.split('.').map(Number); | ||
| return la > ca || (la === ca && (lb > cb || (lb === cb && lc > cc))); | ||
| } | ||
|
|
||
| export async function checkForUpdates() { | ||
| if (!app.isPackaged) return; | ||
|
|
||
| try { | ||
| const res = await fetch('https://api.github.com/repos/internxt/drive-desktop/releases/latestVersion'); | ||
| const data = await res.json(); | ||
| const release = data as { tag_name: string }; | ||
| const latestVersion = release.tag_name.replace(/^v/, ''); | ||
|
|
||
| if (!isNewer(INTERNXT_VERSION, latestVersion)) { | ||
| logger.debug({ msg: 'App is up to date', latestVersion }); | ||
| return; | ||
| } | ||
|
|
||
| const fileName = `Internxt-Setup-${latestVersion}.exe`; | ||
| const filePath = join(tmpdir(), fileName); | ||
|
|
||
| logger.debug({ msg: 'New release available', latestVersion, filePath }); | ||
| const time = await measurePerfomance(async () => { | ||
| const res = await fetch(`https://github.com/internxt/drive-desktop/releases/tag/v2.6.8/${filePath}`); | ||
| await writeFile(filePath, Buffer.from(await res.arrayBuffer())); | ||
| }); | ||
| logger.debug({ msg: 'New release downloaded', latestVersion, time }); | ||
|
|
||
| await verifyHash({ filePath, latestVersion }); | ||
| await showDialog({ filePath, latestVersion }); | ||
| } catch (error) { | ||
| logger.error({ msg: 'Check for updates failed', error }); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { dialog, nativeImage } from 'electron'; | ||
| import { spawn } from 'node:child_process'; | ||
| import { iconPath } from '@/apps/utils/icon'; | ||
|
|
||
| export async function showDialog({ filePath, latestVersion }: { filePath: string; latestVersion: string }) { | ||
| const { response } = await dialog.showMessageBox({ | ||
| type: 'info', | ||
| icon: nativeImage.createFromPath(iconPath), | ||
| title: 'Update Available', | ||
| message: `Version ${latestVersion} is available`, | ||
| detail: 'Download and install the update now?', | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this point, it's already downloaded |
||
| buttons: ['Update Now', 'Later'], | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may be interested in forcing updates always. We do not want clients to use problematic apps if something happens, it's preferable to release a new one and let the autoupdater autoupdate directly
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to, but if the user has the |
||
| }); | ||
|
|
||
| if (response !== 0) return; | ||
|
|
||
| spawn(filePath, ['--updated'], { detached: true, stdio: 'ignore' }).unref(); | ||
|
Check failure on line 17 in src/apps/main/electron/autoupdater/show-dialog.ts
|
||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { logger } from '@internxt/drive-desktop-core/build/backend'; | ||
| import { createHash } from 'node:crypto'; | ||
| import { readFile } from 'node:fs/promises'; | ||
|
|
||
| export async function verifyHash({ filePath, latestVersion }: { filePath: string; latestVersion: string }) { | ||
| const data = await readFile(filePath); | ||
| const actual = createHash('sha512').update(data).digest('base64'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For an app of a couple hundred MBs, it's better to use a stream (pipeline(readable, hasher)) rather than loading the entire binary content in memory
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loading it into memory takes 0.8s and with the pipeline it takes 3.15s, which is time at the startup and that blocks the main thread. Should I change it? |
||
|
|
||
| logger.debug({ msg: 'Verifying release update', actual }); | ||
|
|
||
| const url = `https://github.com/internxt/drive-desktop/releases/download/v${latestVersion}/latest.yml`; | ||
| const res = await fetch(url); | ||
|
Check failure on line 12 in src/apps/main/electron/autoupdater/verify-hash.ts
|
||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| const text = await res.text(); | ||
|
|
||
| const match = /^sha512:\s*(.+)$/m.exec(text); | ||
| if (!match) throw new Error('sha512 not found in latest.yml'); | ||
| const expected = match[1].trim(); | ||
|
|
||
| if (actual !== expected) throw new Error(`sha512 mismatch: expected ${expected}, got ${actual}`); | ||
| logger.debug({ msg: 'Release hash verified', actual, expected }); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The build release script was sometimes generating wrongly the
latest.ymlbecause of the hash.