feat: 🎸 Update desktop through menu option
This commit is contained in:
8 files changed
+260
-30
No files matched your search
@@ -93,4 +93,7 @@ ember-dist/
|
||||
ember-test/
|
||||
|
||||
# CLI
|
||||
cli/
|
||||
cli/
|
||||
|
||||
# Autoupdate
|
||||
nextVersion/
|
||||
@@ -10,7 +10,7 @@ const artifactDestination = path.resolve(__dirname, '..', 'cli');
|
||||
const downloadArtifact = version => {
|
||||
const url = `https://releases.hashicorp.com/boundary/${version}/boundary_${version}_darwin_amd64.zip`;
|
||||
return new Promise((resolve, reject) => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'boundary-artifact-'))
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'boundary-artifact-'));
|
||||
console.log('Create tmp artifact directory: ', tmpDir);
|
||||
|
||||
const artifactFileName = url.split('/').pop();
|
||||
|
||||
@@ -26,33 +26,33 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
packagerConfig: {
|
||||
ignore: [
|
||||
"/ember-test(/|$)",
|
||||
"/tests(/|$)"
|
||||
],
|
||||
name: "Boundary",
|
||||
appBundleId: "com.electron.boundary",
|
||||
ignore: ['/ember-test(/|$)', '/tests(/|$)'],
|
||||
name: 'Boundary',
|
||||
appBundleId: 'com.electron.boundary',
|
||||
// TODO: where should the client version number come from?
|
||||
appVersion: `${formattedAppVersion}${formattedCLIVersion}\n`,
|
||||
appCopyright: "Copyright © 2021 HashiCorp, Inc.",
|
||||
icon: "./config/macos/icon.icns",
|
||||
appCopyright: 'Copyright © 2021 HashiCorp, Inc.',
|
||||
icon: './config/macos/icon.icns',
|
||||
osxSign: {
|
||||
identity: process.env.BOUNDARY_DESKTOP_SIGNING_IDENTITY,
|
||||
"hardened-runtime": true,
|
||||
entitlements: "./config/macos/entitlements.plist",
|
||||
"entitlements-inherit": "./config/macos/entitlements.plist",
|
||||
"signature-flags": "library"
|
||||
}
|
||||
'hardened-runtime': true,
|
||||
entitlements: './config/macos/entitlements.plist',
|
||||
'entitlements-inherit': './config/macos/entitlements.plist',
|
||||
'signature-flags': 'library',
|
||||
},
|
||||
},
|
||||
makers: [
|
||||
{
|
||||
name: "@electron-forge/maker-dmg",
|
||||
name: '@electron-forge/maker-dmg',
|
||||
config: {
|
||||
title: "Boundary",
|
||||
name: "boundary",
|
||||
icon: "./config/macos/disk.icns",
|
||||
background: "./config/macos/background.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
title: 'Boundary',
|
||||
name: 'boundary',
|
||||
icon: './config/macos/disk.icns',
|
||||
background: './config/macos/background.png',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-zip',
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -25,11 +25,13 @@
|
||||
"electron-is-dev": "^1.2.0",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"lookpath": "^1.1.0",
|
||||
"node-html-parser": "^3.1.3",
|
||||
"shell-quote": "^1.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "6.0.0-beta.54",
|
||||
"@electron-forge/maker-dmg": "^6.0.0-beta.54",
|
||||
"@electron-forge/maker-zip": "^6.0.0-beta.54",
|
||||
"decompress": "^4.2.1",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "12.0.2"
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('https');
|
||||
const { parse } = require('node-html-parser');
|
||||
const { autoUpdater, dialog } = require('electron');
|
||||
|
||||
const debug = process.env.DEBUG_APP_UPDATER
|
||||
const releasesUrl = 'https://releases.hashicorp.com/boundary-desktop/';
|
||||
const currentVersion = '1.0.0-beta';
|
||||
|
||||
// Query releases url to find latest version
|
||||
const findLatestVersion = (url) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = '';
|
||||
https.get(url, (response) => {
|
||||
response.on('data', (chunk) => (data += chunk));
|
||||
response.on('end', () => {
|
||||
const html = parse(data);
|
||||
// Ignore first link as it navigates to root
|
||||
const fullVersion = html.querySelectorAll('a')[1].innerHTML;
|
||||
resolve(fullVersion.split('_')[1]);
|
||||
});
|
||||
response.on('error', (err) => reject(err));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Create update config using downloaded archive
|
||||
const createAppUpdaterConfig = (url, version, destination) => {
|
||||
if (debug) console.log(`[app-updater] url: ${url}, destination: ${destination}`);
|
||||
const json = { url, version};
|
||||
const config = JSON.stringify(json);
|
||||
const configPath = `${destination}/feed.json`;
|
||||
if (debug) console.log(`[app-updater] config: ${config}`);
|
||||
fs.writeFileSync(configPath, config);
|
||||
return configPath;
|
||||
};
|
||||
|
||||
const downloadAndInstallUpdate = async (version) => {
|
||||
const url = `${releasesUrl}boundary-desktop_${version}/boundary-desktop_${version}_darwin_amd64.zip`;
|
||||
const destination = path.resolve(__dirname, '..', 'nextVersion');
|
||||
if (!fs.existsSync(destination)) fs.mkdirSync(destination);
|
||||
|
||||
try {
|
||||
let configPath;
|
||||
if (debug) {
|
||||
// Support hosted url and file paths
|
||||
const location = process.env.LATEST_VERSION_LOCATION;
|
||||
configPath = createAppUpdaterConfig(
|
||||
location.match(/^https/i) ? location : `file://${location}`,
|
||||
version,
|
||||
destination
|
||||
);
|
||||
} else {
|
||||
configPath = createAppUpdaterConfig(url, version, destination);
|
||||
}
|
||||
|
||||
autoUpdater.on('update-downloaded', () => {
|
||||
const dialogOpts = {
|
||||
type: 'info',
|
||||
buttons: ['Restart', 'Later'],
|
||||
detail:
|
||||
'A new version has been downloaded. Restart the application to apply the updates.',
|
||||
};
|
||||
dialog.showMessageBox(dialogOpts).then((returnValue) => {
|
||||
if (returnValue.response === 0) autoUpdater.quitAndInstall(true, true);
|
||||
});
|
||||
});
|
||||
|
||||
autoUpdater.on('error', (e) => {
|
||||
dialog.showErrorBox('Could not update', e.message);
|
||||
});
|
||||
|
||||
if (debug) console.log('[app-updater] config:', configPath);
|
||||
autoUpdater.setFeedURL(`file://${configPath}`);
|
||||
autoUpdater.checkForUpdates();
|
||||
} catch (e) {
|
||||
dialog.showErrorBox('Could not update', e.message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure inbuilt app updater to use a custom config file
|
||||
* to download and install next available app version.
|
||||
* TODO: download progress in dialog
|
||||
* TODO: Read current version from app config
|
||||
**/
|
||||
module.exports = {
|
||||
run: async () => {
|
||||
let latestVersion;
|
||||
if (debug) {
|
||||
latestVersion = process.env.LATEST_VERSION_TAG;
|
||||
} else {
|
||||
latestVersion = await findLatestVersion(releasesUrl);
|
||||
}
|
||||
|
||||
// Update not available - do nothing
|
||||
if (latestVersion <= currentVersion) {
|
||||
const dialogOpts = {
|
||||
type: 'info',
|
||||
icon: null,
|
||||
detail: 'No updates available',
|
||||
};
|
||||
|
||||
dialog.showMessageBox(dialogOpts);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update is available - prompt for download
|
||||
const dialogOpts = {
|
||||
type: 'info',
|
||||
buttons: ['Download', 'Later'],
|
||||
icon: null,
|
||||
detail: 'A new version is available for download',
|
||||
};
|
||||
|
||||
dialog.showMessageBox(dialogOpts).then((returnValue) => {
|
||||
if (returnValue.response === 0) {
|
||||
downloadAndInstallUpdate(latestVersion);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -11,6 +11,7 @@ const {
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
Menu,
|
||||
MenuItem,
|
||||
} = require('electron');
|
||||
require('./handlers.js');
|
||||
|
||||
@@ -18,7 +19,6 @@ const origin = require('./origin.js');
|
||||
const { generateCSPHeader } = require('./content-security-policy.js');
|
||||
|
||||
const menu = require('./menu.js');
|
||||
|
||||
const isDev = require('electron-is-dev');
|
||||
|
||||
// Register the custom file protocol
|
||||
@@ -101,11 +101,13 @@ app.on('ready', async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Configure menu in prod env
|
||||
if (!isDev) {
|
||||
const menuTemplate = Menu.buildFromTemplate(menu.generateMenuTemplate());
|
||||
Menu.setApplicationMenu(menuTemplate);
|
||||
// Configure dev tools menu
|
||||
const menuTemplate = Menu.buildFromTemplate(menu.generateMenuTemplate());
|
||||
if (isDev) {
|
||||
const view = menuTemplate.getMenuItemById('view');
|
||||
view.submenu.append(new MenuItem({ role: 'toggleDevTools' }));
|
||||
}
|
||||
Menu.setApplicationMenu(menuTemplate);
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1280,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { shell } = require('electron');
|
||||
const appUpdater = require('./app-updater.js');
|
||||
|
||||
const generateMenuTemplate = () => {
|
||||
return [
|
||||
@@ -7,6 +8,11 @@ const generateMenuTemplate = () => {
|
||||
label: 'Boundary',
|
||||
submenu: [
|
||||
{ role: 'about' },
|
||||
{
|
||||
id: 'update',
|
||||
label: 'Check for Updates',
|
||||
click: async () => appUpdater.run(),
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
@@ -44,6 +50,7 @@ const generateMenuTemplate = () => {
|
||||
},
|
||||
// { role: 'viewMenu' }
|
||||
{
|
||||
id: 'view',
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{ role: 'reload' },
|
||||
|
||||
@@ -155,6 +155,16 @@
|
||||
optionalDependencies:
|
||||
electron-installer-dmg "^3.0.0"
|
||||
|
||||
"@electron-forge/maker-zip@^6.0.0-beta.54":
|
||||
version "6.0.0-beta.54"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-6.0.0-beta.54.tgz#83d322afd912587fd233e87c30339d8150f29bed"
|
||||
integrity sha512-wbJhK1rDOCZMTtKrjvavT8R+Yi+v/6axsnTXvzbkzzMQ0xADKNslTwzO6mmbBJea4oIbYmQ44DRAjI21TNyQ/A==
|
||||
dependencies:
|
||||
"@electron-forge/maker-base" "6.0.0-beta.54"
|
||||
"@electron-forge/shared-types" "6.0.0-beta.54"
|
||||
cross-zip "^3.0.0"
|
||||
fs-extra "^9.0.1"
|
||||
|
||||
"@electron-forge/plugin-base@6.0.0-beta.54":
|
||||
version "6.0.0-beta.54"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-6.0.0-beta.54.tgz#1847eeee00e9558d61ef9ff7c2d7c9f5dbf1109c"
|
||||
@@ -508,6 +518,11 @@ bluebird@^3.1.1, bluebird@^3.5.0:
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||
|
||||
boolbase@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
|
||||
|
||||
boolean@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.2.tgz#df1baa18b6a2b0e70840475e1d93ec8fe75b2570"
|
||||
@@ -791,6 +806,29 @@ cross-spawn@^7.0.1:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cross-zip@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cross-zip/-/cross-zip-3.1.0.tgz#2b7d33f2a893bf83e232ccbabf4c6c706f6b313c"
|
||||
integrity sha512-aX02l0SD3KE27pMl69gkxDdDM5D3u9Ic4Je+2b1B2fP0dWnlWWY6ns2Vk5DEgCXJRhL3GasSpicNQRNbDkq0+w==
|
||||
dependencies:
|
||||
rimraf "^3.0.0"
|
||||
|
||||
css-select@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/css-select/-/css-select-3.1.2.tgz#d52cbdc6fee379fba97fb0d3925abbd18af2d9d8"
|
||||
integrity sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
css-what "^4.0.0"
|
||||
domhandler "^4.0.0"
|
||||
domutils "^2.4.3"
|
||||
nth-check "^2.0.0"
|
||||
|
||||
css-what@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-4.0.0.tgz#35e73761cab2eeb3d3661126b23d7aa0e8432233"
|
||||
integrity sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==
|
||||
|
||||
currently-unhandled@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
|
||||
@@ -956,6 +994,36 @@ devtron@^1.4.0:
|
||||
highlight.js "^9.3.0"
|
||||
humanize-plus "^1.8.1"
|
||||
|
||||
dom-serializer@^1.0.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.2.0.tgz#3433d9136aeb3c627981daa385fc7f32d27c48f1"
|
||||
integrity sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==
|
||||
dependencies:
|
||||
domelementtype "^2.0.1"
|
||||
domhandler "^4.0.0"
|
||||
entities "^2.0.0"
|
||||
|
||||
domelementtype@^2.0.1, domelementtype@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
|
||||
integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
|
||||
|
||||
domhandler@^4.0.0, domhandler@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.1.0.tgz#c1d8d494d5ec6db22de99e46a149c2a4d23ddd43"
|
||||
integrity sha512-/6/kmsGlMY4Tup/nGVutdrK9yQi4YjWVcVeoQmixpzjOUK1U7pQkvAPHBJeUxOgxF0J8f8lwCJSlCfD0V4CMGQ==
|
||||
dependencies:
|
||||
domelementtype "^2.2.0"
|
||||
|
||||
domutils@^2.4.3:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.5.1.tgz#9b8e84b5d9f788499ae77506ea832e9b4f9aa1c0"
|
||||
integrity sha512-hO1XwHMGAthA/1KL7c83oip/6UWo3FlUNIuWiWKltoiQ5oCOiqths8KknvY2jpOohUoUgnwa/+Rm7UpwpSbY/Q==
|
||||
dependencies:
|
||||
dom-serializer "^1.0.1"
|
||||
domelementtype "^2.2.0"
|
||||
domhandler "^4.1.0"
|
||||
|
||||
ds-store@^0.1.5:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/ds-store/-/ds-store-0.1.6.tgz#d1024ef746ed0c13f0f7fec85c7e858e8c4b7ca7"
|
||||
@@ -1102,6 +1170,11 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
entities@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||
|
||||
env-paths@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43"
|
||||
@@ -1614,6 +1687,11 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
he@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||
|
||||
highlight.js@^10.4.1, highlight.js@^9.3.0:
|
||||
version "10.6.0"
|
||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.6.0.tgz#0073aa71d566906965ba6e1b7be7b2682f5e18b6"
|
||||
@@ -2277,6 +2355,14 @@ node-gyp@^7.1.0:
|
||||
tar "^6.0.2"
|
||||
which "^2.0.2"
|
||||
|
||||
node-html-parser@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-3.1.3.tgz#987d39bc8df27bc70cbe3b4e9a31fd84f7454dfb"
|
||||
integrity sha512-pCE2I5UY5iOBnWdJQkbYZSk+fyq2zepw0nsELpHQjVFyCzOeZhkMhnvKqGceKgzWsWx7EG4KtMqsy9Eklf5Thw==
|
||||
dependencies:
|
||||
css-select "^3.1.2"
|
||||
he "1.2.0"
|
||||
|
||||
node-pre-gyp@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054"
|
||||
@@ -2369,6 +2455,13 @@ npmlog@^4.0.2, npmlog@^4.1.2:
|
||||
gauge "~2.7.3"
|
||||
set-blocking "~2.0.0"
|
||||
|
||||
nth-check@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125"
|
||||
integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
|
||||
nugget@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0"
|
||||
@@ -2943,7 +3036,7 @@ rimraf@^2.6.1, rimraf@^2.7.1:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^3.0.2:
|
||||
rimraf@^3.0.0, rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
|
||||
Reference in new issue
Block a user