Add notarisation to osx build process; implement auto updates

This commit is contained in:
Martin Kleinschrodt 2019-10-02 17:21:21 +02:00
parent 3f0eccedca
commit 86996d7d00
7 changed files with 357 additions and 159 deletions

2
.gitignore vendored
View File

@ -15,3 +15,5 @@ packages/cordova/www
packages/cordova/dist
data
packages/electron/build
packages/electron/app
packages/electron/dist

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,17 @@
const { notarize } = require("electron-notarize");
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== "darwin") {
return;
}
const appName = context.packager.appInfo.productFilename;
return await notarize({
appBundleId: "app.padloc",
appPath: `${appOutDir}/${appName}.app`,
appleId: "martin@maklesoft.com",
appleIdPassword: "@keychain:AC_PASSWORD"
});
};

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,30 @@
{
"name": "@padloc/electron",
"version": "3.0.0",
"version": "3.0.4",
"description": "Electron Wrapper for Padloc app",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"repository": {
"type": "git",
"url": "https://github.com/padloc/padloc.git"
},
"author": "",
"scripts": {
"build": "rm -r app && webpack && electron-builder",
"run": "electron/app/main.js"
},
"author": "MaKleSoft UG",
"license": "GPL-3.0",
"dependencies": {
"@padloc/app": "^3.0.0",
"@padloc/core": "^3.0.0",
"electron": "^6.0.7",
"electron-store": "^4.0.0",
"electron-updater": "^4.1.2"
},
"devDependencies": {
"electron-builder": "^21.2.0",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.0.0",
"electron": "^6.0.7",
"electron-builder": "^21.2.0",
"electron-notarize": "^0.1.1",
"file-loader": "^4.0.0",
"html-webpack-plugin": "^3.2.0",
"style-loader": "^0.23.1",
@ -26,7 +32,17 @@
"webpack": "^4.35.3",
"webpack-cli": "^3.3.5"
},
"scripts": {
"build": "webpack"
"build": {
"appId": "app.padloc",
"directories": {
"app": "app"
},
"mac": {
"hardenedRuntime" : true,
"gatekeeperAssess": false,
"entitlements": "entitlements.plist",
"entitlementsInherit": "entitlements.plist"
},
"afterSign": "notarize.js"
}
}

View File

@ -3,6 +3,9 @@ import { autoUpdater, UpdateInfo } from "electron-updater";
import * as os from "os";
import ElectronStore from "electron-store";
const debug = process.argv.includes("--debug");
console.log("args: ", process.argv, debug);
const settings = new ElectronStore({
name: "settings",
defaults: {
@ -23,7 +26,7 @@ async function updateReady(updateInfo: UpdateInfo) {
const { response } = await dialog.showMessageBox(win, {
message: "Install Update",
detail:
`Padlock version ${updateInfo.version} has been downloaded. The update will be installed ` +
`Padloc version ${updateInfo.version} has been downloaded. The update will be installed ` +
`the next time the app is launched.`,
buttons: ["Install Later", "Install And Restart"],
defaultId: 1
@ -38,59 +41,61 @@ async function updateReady(updateInfo: UpdateInfo) {
autoUpdater.on("update-downloaded", updateReady);
// function htmlToText(html: string) {
// return html
// .replace(/<p>([\w\W]*?)<\/p>/g, "$1")
// .replace(/<\/?ul>/g, "")
// .replace(/<li>([\w\W]*?)<\/li>/g, "\u2022 $1");
// }
function htmlToText(html: string) {
return html
.replace(/<p>([\w\W]*?)<\/p>/g, "$1")
.replace(/<\/?ul>/g, "")
.replace(/<li>([\w\W]*?)<\/li>/g, "\u2022 $1");
}
// async function updateAvailable(versionInfo) {
// if (autoUpdater.autoDownload) {
// return;
// }
//
// const { response, checkboxChecked } = await dialog.showMessageBox(null, {
// type: "info",
// message: `A new version of Padlock is available! (v${versionInfo.version})`,
// detail: htmlToText(versionInfo.releaseNotes),
// checkboxLabel: "Automatically download and install updates in the future (recommended)",
// buttons: ["Remind Me Later", "Download And Install"],
// defaultId: 1
// });
//
// settings.set("autoDownloadUpdates", checkboxChecked);
//
// if (response === 1) {
// autoUpdater.downloadUpdate();
//
// dialog.showMessageBox({
// message: "Downloading Update...",
// detail: "The new version is being downloaded. You'll be notified when it is ready to be installed!"
// });
// }
// }
async function updateAvailable(versionInfo: UpdateInfo) {
if (autoUpdater.autoDownload) {
return;
}
async function checkForUpdates(_manual = false) {
const { response, checkboxChecked } = await dialog.showMessageBox(win, {
type: "info",
message: `A new version of Padloc is available! (v${versionInfo.version})`,
detail: htmlToText(versionInfo.releaseNotes as string),
checkboxLabel: "Automatically download and install updates in the future (recommended)",
buttons: ["Remind Me Later", "Download And Install"],
defaultId: 1
});
settings.set("autoDownloadUpdates", checkboxChecked);
if (response === 1) {
autoUpdater.downloadUpdate();
dialog.showMessageBox(win, {
message: "Downloading Update...",
detail: "The new version is being downloaded. You'll be notified when it is ready to be installed!"
});
}
}
async function checkForUpdates(manual = false) {
autoUpdater.autoDownload = settings.get("autoDownloadUpdates") as boolean;
autoUpdater.allowPrerelease = settings.get("allowPrerelease") as boolean;
const result = await autoUpdater.checkForUpdates();
// @ts-ignore
console.log("update available: ", result, autoUpdater.updateAvailable);
// if (autoUpdater.updateAvailable) {
// updateAvailable(result.versionInfo);
// } else if (manual) {
// const { checkboxChecked } = await dialog.showMessageBox(null, {
// type: "info",
// message: "No Updates Available",
// detail: "Your version of Padlock is up to date.",
// checkboxLabel: "Automatically download and install updates in the future (recommended)",
// checkboxChecked: settings.get("autoDownloadUpdates") as boolean
// });
//
// settings.set("autoDownloadUpdates", checkboxChecked);
// }
const hasUpdate = typeof result.downloadPromise !== "undefined";
console.log(result, hasUpdate);
if (hasUpdate) {
updateAvailable(result.versionInfo);
} else if (manual) {
const { checkboxChecked } = await dialog.showMessageBox(win, {
type: "info",
message: "No Updates Available",
detail: "Your version of Padloc is up to date.",
checkboxLabel: "Automatically download and install updates in the future (recommended)",
checkboxChecked: settings.get("autoDownloadUpdates") as boolean
});
settings.set("autoDownloadUpdates", checkboxChecked);
}
}
function createWindow() {
@ -109,16 +114,14 @@ function createWindow() {
hasShadow: true,
show: false,
webPreferences: {
devTools: true
devTools: debug
}
});
win.loadFile("index.html");
win.once("ready-to-show", () => {
console.log("showing window");
win.show();
win.webContents.openDevTools();
});
win.on("close", () => {
@ -146,7 +149,7 @@ function createApplicationMenu() {
};
const appSubMenu: any[] =
os.platform() === "darwin" ? [{ role: "about" }] : [{ label: `Padlock v${app.getVersion()}`, enabled: false }];
os.platform() === "darwin" ? [{ role: "about" }] : [{ label: `Padloc v${app.getVersion()}`, enabled: false }];
appSubMenu.push(checkForUpdatesItem);
@ -154,21 +157,21 @@ function createApplicationMenu() {
appSubMenu.push({ type: "separator" }, { role: "hide" }, { role: "hideothers" }, { role: "unhide" });
}
// if (debug) {
// appSubMenu.push(
// { type: "separator" },
// {
// label: "Debug",
// submenu: [
// {
// label: "Open Dev Tools",
// accelerator: "CmdOrCtrl+Shift+I",
// click: () => win.webContents.toggleDevTools()
// }
// ]
// }
// );
// }
if (debug) {
appSubMenu.push(
{ type: "separator" },
{
label: "Debug",
submenu: [
{
label: "Open Dev Tools",
accelerator: "CmdOrCtrl+Shift+I",
click: () => win.webContents.toggleDevTools()
}
]
}
);
}
appSubMenu.push({ type: "separator" }, { role: "quit" });

View File

@ -1,7 +1,7 @@
const path = require("path");
const { EnvironmentPlugin, optimize } = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { version } = require("./package.json");
const { description, author, version } = require("./package.json");
module.exports = [
{
@ -10,7 +10,7 @@ module.exports = [
app: path.resolve(__dirname, "src/index.ts")
},
output: {
path: path.resolve(__dirname, "build"),
path: path.resolve(__dirname, "app"),
filename: "[name].js",
chunkFilename: "[name].chunk.js"
},
@ -70,7 +70,7 @@ module.exports = [
main: path.resolve(__dirname, "src/main.ts")
},
output: {
path: path.resolve(__dirname, "build"),
path: path.resolve(__dirname, "app"),
filename: "[name].js",
chunkFilename: "[name].chunk.js"
},
@ -91,7 +91,22 @@ module.exports = [
new EnvironmentPlugin({
PL_SERVER_URL: `http://localhost:${process.env.PL_SERVER_PORT || 3000}`,
PL_STRIPE_PUBLIC_KEY: null
})
}),
{
apply(compiler) {
const package = JSON.stringify({ name: "Padloc", description, version, main: "main.js" });
// emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well
compiler.hooks.emit.tapAsync("InjectAppPackage", (compilation, callback) => {
// Insert this list into the webpack build as a new file asset:
compilation.assets["package.json"] = {
source: () => package,
size: () => package.length
};
callback();
});
}
}
]
}
];