Skip to content
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

Build electron app from pre-built tarball #1

Merged
merged 7 commits into from
Dec 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .buildkite/pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
steps:
- label: ":eslint: Lint"
command:
- "yarn install"
- "yarn lint"
plugins:
- docker#v3.0.1:
image: "node:10"
19 changes: 19 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const jsSdkEslintCfg = require('matrix-js-sdk/.eslintrc');

module.exports = {
parserOptions: {
ecmaVersion: 8,
},
env: {
node: true,
// we also have some browser code (ie. the preload script)
browser: true,
},
extends: ["eslint:recommended", "google"],
rules: jsSdkEslintCfg.rules,
}

// js-sdk uses a babel rule which we can't use because we
// don't use babel, so remove it & put the original back
delete module.exports.rules["babel/no-invalid-this"];
module.exports.rules["no-invalid-this"] = "error";
7 changes: 7 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Riot Desktop
============

This is *not* where the source for Riot desktop lives... yet. As of now,
it still lives in the main riot-web repo: https://github.com/vector-im/riot-web

This is an experimental split-out of the Riot desktop code from the main repo.
87 changes: 87 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"name": "riot-desktop",
"productName": "Riot",
"main": "src/electron-main.js",
"version": "1.5.5",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"repository": {
"type": "git",
"url": "https://github.com/vector-im/riot-desktop"
},
"license": "Apache-2.0",
"files": [],
"scripts": {
"mkdirs": "mkdir -p packages && mkdir -p deploys",
"fetch": "yarn run mkdirs && scripts/fetch-package.js",
"check": "scripts/check-webapp.js",
"start": "yarn run check && yarn install:electron && electron .",
"install:electron": "electron-builder install-app-deps",
"lint": "eslint src/",
"build:electron": "yarn check && electron-builder",
"clean": "rimraf webapp dist packages deploys"
},
"dependencies": {
"auto-launch": "^5.0.1",
"electron-store": "^2.0.0",
"electron-window-state": "^4.1.0",
"minimist": "^1.2.0",
"png-to-ico": "^1.0.2"
},
"devDependencies": {
"electron-builder": "^21.2.0",
jryans marked this conversation as resolved.
Show resolved Hide resolved
"electron-builder-squirrel-windows": "^21.2.0",
"electron-devtools-installer": "^2.2.4",
"electron-notarize": "^0.2.0",
"eslint": "^5.8.0",
"eslint-config-google": "^0.7.1",
"eslint-plugin-babel": "^4.1.2",
"follow-redirects": "^1.9.0",
"matrix-js-sdk": "^2.4.6-rc.1",
"tar": "^5.0.5"
},
"build": {
"appId": "im.riot.app",
"electronVersion": "7.1.3",
"files": [
"node_modules/**",
"src/**"
],
"extraResources": [
{
"from": "res/img",
"to": "img"
},
"webapp/**/*"
],
"linux": {
"target": "deb",
"category": "Network;InstantMessaging;Chat",
"maintainer": "support@riot.im",
"desktop": {
"StartupWMClass": "riot"
}
},
"deb": {
"afterInstall": "build/linux/after-install.tpl"
},
"mac": {
"category": "public.app-category.social-networking",
"darkModeSupport": true
},
"win": {
"target": {
"target": "squirrel",
"arch": [
"x64",
"ia32"
]
},
"sign": "scripts/electron_winSign"
},
"directories": {
"output": "dist"
},
"afterSign": "scripts/electron_afterSign.js"
}
}
15 changes: 15 additions & 0 deletions scripts/check-webapp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env node

const fs = require('fs').promises;

async function main() {
try {
const webappDir = await fs.opendir('webapp');
return 0;
} catch (e) {
console.log("No 'webapp' directory found. Run 'yarn run fetch' or symlink manually");
return 1;
}
}

main().then((ret) => process.exit(ret));
184 changes: 184 additions & 0 deletions scripts/fetch-package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#!/usr/bin/env node

const process = require('process');
const path = require('path');
const fs = require('fs');
const fsPromises = require('fs').promises;
const { https } = require('follow-redirects');
const child_process = require('child_process');
const tar = require('tar');

const riotDesktopPackageJson = require('../package.json');

const PUB_KEY_URL = "https://packages.riot.im/riot-release-key.asc";
const PACKAGE_URL_PREFIX = "https://github.com/vector-im/riot-web/releases/download/";

async function downloadToFile(url, filename) {
console.log("Downloading " + url + "...");
const outStream = await fs.createWriteStream(filename);

return new Promise((resolve, reject) => {
https.get(url, (resp) => {
if (resp.statusCode / 100 !== 2) {
reject("Download failed: " + resp.statusCode);
return;
}

resp.on('data', (chunk) => {
outStream.write(chunk);
});
resp.on('end', (chunk) => {
outStream.end();
resolve();
});
});
}).catch(async (e) => {
outStream.end();
await fsPromises.unlink(filename);
throw e;
});
}

async function verifyFile(filename) {
return new Promise((resolve, reject) => {
const gpgProc = child_process.execFile('gpg', ['--verify', filename + '.asc', filename], (error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}

async function main() {
let verify = true;
let importkey = false;
let pkgDir = 'packages';
let deployDir = 'deploys';
let targetVersion;

while (process.argv.length > 2) {
switch (process.argv[2]) {
case '--noverify':
verify = false;
break;
case '--importkey':
importkey = true;
break;
case '--packages':
process.argv.shift();
pkgDir = process.argv[2];
break;
case '--deploys':
process.argv.shift();
deployDir = process.argv[2];
break;
default:
targetVersion = process.argv[2];
}
process.argv.shift();
}

if (targetVersion === undefined) {
targetVersion = 'v' + riotDesktopPackageJson.version;
}

const haveGpg = await new Promise((resolve) => {
child_process.execFile('gpg', ['--version'], (error) => {
resolve(!error);
});
});

if (importkey) {
if (!haveGpg) {
console.log("Can't import key without working GPG binary: install GPG and try again");
return 1;
}

await new Promise((resolve) => {
const gpgProc = child_process.execFile('gpg', ['--import'], (error) => {
if (error) {
console.log("Failed to import key", error);
} else {
console.log("Key imported!");
}
resolve(!error);
});
https.get(PUB_KEY_URL, (resp) => {
resp.on('data', (chunk) => {
gpgProc.stdin.write(chunk);
});
resp.on('end', (chunk) => {
gpgProc.stdin.end();
});
});
});
}

if (verify && !haveGpg) {
console.log("No working GPG binary: install GPG or pass --noverify to skip verification");
return 1;
}

const haveDeploy = false;
const expectedDeployDir = path.join(deployDir, 'riot-' + targetVersion);
try {
const webappDir = await fs.opendir(expectedDeployDir);
console.log(expectedDeployDir + "already exists");
haveDeploy = true;
} catch (e) {
}

if (!haveDeploy) {
const filename = 'riot-' + targetVersion + '.tar.gz';
const outPath = path.join(pkgDir, filename);
const url = PACKAGE_URL_PREFIX + targetVersion + '/' + filename;
try {
await fsPromises.stat(outPath);
console.log("Already have " + filename + ": not redownloading");
} catch (e) {
try {
await downloadToFile(url, outPath);
} catch (e) {
console.log("Failed to download " + url, e);
return 1;
}
}

if (verify) {
try {
await fsPromises.stat(outPath+'.asc');
console.log("Already have " + filename + ".asc: not redownloading");
} catch (e) {
try {
await downloadToFile(url + '.asc', outPath + '.asc');
} catch (e) {
console.log("Failed to download " + url, e);
return 1;
}
}

try {
await verifyFile(outPath);
console.log(outPath + " downloaded and verified");
} catch (e) {
console.log("Signature verification failed!", e);
return 1;
}
} else {
console.log(outPath + " downloaded but NOT verified");
}

await tar.x({
file: outPath,
cwd: deployDir,
});
}

console.log("Symlink " + expectedDeployDir + " -> webapp");
// Does this do a sensible thing on Windows?
await fsPromises.symlink(expectedDeployDir, 'webapp');
}

main().then((ret) => process.exit(ret));
24 changes: 3 additions & 21 deletions src/electron-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const tray = require('./tray');
const vectorMenu = require('./vectormenu');
const webContentsHandler = require('./webcontents-handler');
const updater = require('./updater');
const { migrateFromOldOrigin } = require('./originMigrator');
jryans marked this conversation as resolved.
Show resolved Hide resolved

const windowStateKeeper = require('electron-window-state');
const Store = require('electron-store');
Expand Down Expand Up @@ -64,11 +63,6 @@ if (argv["help"]) {
app.exit();
}

// boolean flag set whilst we are doing one-time origin migration
// We only serve the origin migration script while we're actually
// migrating to mitigate any risk of it being used maliciously.
let migratingOrigin = false;

if (argv['profile-dir']) {
app.setPath('userData', argv['profile-dir']);
} else if (argv['profile']) {
Expand All @@ -77,7 +71,7 @@ if (argv['profile-dir']) {

let vectorConfig = {};
try {
vectorConfig = require('../../webapp/config.json');
vectorConfig = require('../webapp/config.json');
} catch (e) {
// it would be nice to check the error code here and bail if the config
// is unparseable, but we get MODULE_NOT_FOUND in the case of a missing
Expand Down Expand Up @@ -231,11 +225,6 @@ ipcMain.on('ipcCall', async function(ev, payload) {
mainWindow.focus();
}
break;
case 'origin_migrate':
migratingOrigin = true;
await migrateFromOldOrigin();
migratingOrigin = false;
break;
case 'getConfig':
ret = vectorConfig;
break;
Expand Down Expand Up @@ -476,15 +465,8 @@ app.on('ready', () => {
}

let baseDir;
// first part of the path determines where we serve from
if (migratingOrigin && target[1] === 'origin_migrator_dest') {
// the origin migrator destination page
// (only the destination script needs to come from the
// custom protocol: the source part is loaded from a
// file:// as that's the origin we're migrating from).
baseDir = __dirname + "/../../origin_migrator/dest";
} else if (target[1] === 'webapp') {
baseDir = __dirname + "/../../webapp";
if (target[1] === 'webapp') {
baseDir = path.join(__dirname, "../webapp");
} else {
callback({error: -6}); // FILE_NOT_FOUND
return;
Expand Down
Loading