Skip to content
This repository was archived by the owner on Jul 26, 2023. It is now read-only.

Commit af6f46b

Browse files
committed
feat(core): adding support for checking for updates on schedule
Using a cron pattern for update schedules.
1 parent 12ce6d0 commit af6f46b

File tree

9 files changed

+87
-13
lines changed

9 files changed

+87
-13
lines changed

docs/config/updatePolicy/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The specification for an update policy.
2121
| checkForUpdates | `boolean` | Whether to check for updates. |
2222
| parameters | `UpdateParameters` | Key value map to override parameters in the specified update provider. |
2323
| provider | `string` | The update source. |
24+
| schedule | `string` | Sets an update schedule using a cron format. |
2425

2526
## Example
2627

@@ -33,4 +34,5 @@ metadata:
3334
namespace: desktop
3435
spec:
3536
checkForUpdates: true
37+
schedule: 0 * * * *
3638
```

package-lock.json

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"devDependencies": {
4545
"@types/compression": "^1.7.0",
4646
"@types/cors": "2.8.8",
47+
"@types/cron": "^1.7.2",
4748
"@types/express": "^4.17.9",
4849
"@types/express-useragent": "^1.0.0",
4950
"@types/express-ws": "^3.0.0",
@@ -75,6 +76,7 @@
7576
"copy-webpack-plugin": "^6.4.0",
7677
"copyfiles": "^2.4.1",
7778
"cors": "^2.8.5",
79+
"cron": "1.7.2",
7880
"cross-var": "^1.1.0",
7981
"csp-html-webpack-plugin": "^4.0.0",
8082
"css-loader": "^5.0.1",

packages/desktop-core/src/main/launcher/trayLauncherService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ export class TrayLauncherService implements ILauncherService {
2121

2222
this.logger.verbose(`Configuring tray: ${name} in ${namespace}`);
2323

24-
await this.trayService.create(configuration);
24+
const instance = await this.trayService.create(configuration);
2525

26-
return configuration;
26+
return instance.configuration;
2727
}
2828
}

packages/desktop-core/src/main/launcher/updatePolicyLauncherService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ export class UpdatePolicyLauncherService implements ILauncherService {
2121

2222
this.logger.verbose(`Configuring updates: ${name} in ${namespace}`);
2323

24-
return this.updateService.configure(configuration);
24+
return this.updateService.create(configuration);
2525
}
2626
}

packages/desktop-core/src/main/updates/defaultUpdateService.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { IConfiguration, IUpdatePolicySpecification } from "@reactivemarkets/desktop-types";
2-
import { autoUpdater } from "electron-updater";
2+
import { app, Notification } from "electron";
3+
import { autoUpdater, UpdateDownloadedEvent } from "electron-updater";
4+
import { CronJob, job } from "cron";
35
import numeral from "numeral";
46
import { logger } from "../logging";
57
import { IUpdateService } from "./iUpdateService";
68

79
export class DefaultUpdateService implements IUpdateService {
8-
public configure(configuration: IConfiguration): Promise<IConfiguration> {
10+
private cronJob?: CronJob;
11+
12+
public create(configuration: IConfiguration): Promise<IConfiguration> {
913
const spec = configuration.spec as IUpdatePolicySpecification | undefined;
1014
if (!spec?.checkForUpdates) {
1115
return Promise.resolve(configuration);
@@ -18,12 +22,14 @@ export class DefaultUpdateService implements IUpdateService {
1822
})
1923
.on("update-available", () => {
2024
logger.info("Update available.");
25+
26+
this.cronJob?.stop();
2127
})
2228
.on("update-not-available", () => {
2329
logger.info("Update not available.");
2430
})
2531
.on("error", (error) => {
26-
logger.info(`Error in auto-updater. ${error}`);
32+
logger.info(`Error in auto-updater. ${error?.message}`);
2733
})
2834
.on("download-progress", (progress) => {
2935
const { bytesPerSecond, percent, total, transferred } = progress;
@@ -38,24 +44,41 @@ export class DefaultUpdateService implements IUpdateService {
3844

3945
logger.info(`${percentComplete}% => (${transferredBytes}/${totalBytes}) ${downloadSpeed}/s`);
4046
})
41-
.on("update-downloaded", () => {
42-
logger.info("Update downloaded.");
47+
.once("update-downloaded", (update: UpdateDownloadedEvent) => {
48+
const { version } = update;
49+
logger.info(`${version} downloaded.`);
50+
51+
const notification = new Notification({
52+
title: "A new update is ready to install",
53+
body: `${app.name} version ${version} has been downloaded, click to restart now.`,
54+
});
55+
notification.once("click", () => {
56+
autoUpdater.quitAndInstall(true, true);
57+
});
58+
notification.show();
4359
});
4460

45-
if (spec?.channel !== undefined) {
61+
if (spec.channel !== undefined) {
4662
autoUpdater.channel = spec.channel;
4763
}
4864

49-
if (spec?.provider !== undefined) {
65+
if (spec.provider !== undefined) {
5066
autoUpdater.setFeedURL({
5167
...spec?.parameters,
5268
provider: spec.provider,
5369
});
5470
}
5571

72+
if (spec.schedule !== undefined) {
73+
this.cronJob = job(spec.schedule, () => {
74+
autoUpdater.checkForUpdates();
75+
});
76+
this.cronJob.start();
77+
}
78+
5679
autoUpdater.allowDowngrade = spec?.allowDowngrade ?? true;
5780
autoUpdater.allowPrerelease = spec?.allowPrerelease ?? false;
58-
autoUpdater.checkForUpdatesAndNotify();
81+
autoUpdater.checkForUpdates();
5982

6083
return Promise.resolve(configuration);
6184
}

packages/desktop-core/src/main/updates/iUpdateService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { IConfiguration } from "@reactivemarkets/desktop-types";
22

33
export interface IUpdateService {
44
/**
5-
* Configure updates based on the given configuration.
5+
* Configure updates based on the given `configuration`.
66
* @param configuration The update configuration.
77
*/
8-
configure(configuration: IConfiguration): Promise<IConfiguration>;
8+
create(configuration: IConfiguration): Promise<IConfiguration>;
99
}

packages/desktop-types/src/configuration/iUpdatePolicySpecification.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,16 @@ export interface IUpdatePolicySpecification {
3030
* The update source.
3131
*/
3232
readonly provider?: "generic" | "github" | "s3";
33+
34+
/**
35+
* Cron based update schedule.
36+
*
37+
* ### Examples
38+
*
39+
* Hourly check:
40+
* ```
41+
* 0 * * * *
42+
* ```
43+
*/
44+
readonly schedule?: string;
3345
}

packages/desktop/build/app-defaults.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ metadata:
2020
namespace: desktop
2121
spec:
2222
checkForUpdates: true
23+
schedule: 0 * * * *
2324
---
2425
kind: applicationSecurityPolicy
2526
metadata:

0 commit comments

Comments
 (0)