Merge pull request #1017 from Mikunj/clean-config

Clean config
pull/1018/head
Vince 5 years ago committed by GitHub
commit 7e2110015f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -82,40 +82,46 @@ while you make changes:
yarn grunt dev # runs until you stop it, re-generating built assets on file changes
```
## Additional storage profiles
## Multiple instances
Since there is no registration for Session, you can create as many accounts as you
can public keys. To test the P2P functionality on the same machine, however, requries
that each client binds their message server to a different port.
can public keys. Each client however has a dedicated storage profile which is determined by the environment and instance variables.
You can use the following command to start a client bound to a different port.
This profile will change [userData](https://electron.atom.io/docs/all/#appgetpathname)
directory from `%appData%/Session` to `%appData%/Session-{environment}-{instance}`.
There are a few scripts which you can use:
```
yarn start-multi
yarn start - Start development
yarn start-multi - Start second instance of development
yarn start-prod - Start production but in development mode
yarn start-prod-multi - Start another instance of production
```
For more than 2 clients, you can setup additional storage profiles and switch
between them using the `NODE_APP_INSTANCE` environment variable and specifying a
new localServerPort in the config.
For example, to create an 'alice' profile, put a file called `local-alice.json` in the
`config` directory:
For more than 2 clients, you may run the above command with `NODE_APP_INSTANCE` set before them.
For example, running:
```
{
"storageProfile": "aliceProfile",
"localServerPort": "8082",
}
NODE_APP_INSTANCE=alice yarn start
```
Then you can start up the application a little differently to load the profile:
Will run the development environment with the `alice` instance and thus create a seperate storage profile.
If a fixed profile is needed (in the case of tests), you can specify it using `storageProfile` in the config file. If the change is local then put it in `local-{instance}.json` otherwise put it in `default-{instance}.json` or `{env}-{instance}.json`.
Local config files will be ignored by default in git.
For example, to create an 'alice' profile locally, put a file called `local-alice.json` in the
`config` directory:
```
NODE_APP_INSTANCE=alice yarn run start
{
"storageProfile": "alice-profile",
}
```
This changes the [userData](https://electron.atom.io/docs/all/#appgetpathname)
directory from `%appData%/Session` to `%appData%/Session-aliceProfile`.
This will then set the `userData` directory to `%appData%/Session-alice-profile` when running the `alice` instance.
# Making changes
@ -187,26 +193,11 @@ Above all, spend some time with the repository. Follow the pull request template
your pull request description automatically. Take a look at recent approved pull requests,
see how they did things.
## Testing Production Builds
## Production Builds
To test changes to the build system, build a release using
You can build a production binary by running the following:
```
yarn generate
yarn build-release
```
Then, run the tests using `grunt test-release:osx --dir=release`, replacing `osx` with `linux` or `win` depending on your platform.
<!-- TODO:
## Translations
To pull the latest translations, follow these steps:
1. Download Transifex client:
https://docs.transifex.com/client/installing-the-client
2. Create Transifex account: https://transifex.com
3. Generate API token: https://www.transifex.com/user/settings/api/
4. Create `~/.transifexrc` configuration:
https://docs.transifex.com/client/client-configuration#-transifexrc
5. Run `yarn grunt tx`. -->

@ -1,12 +1,13 @@
const path = require('path');
const electronIsDev = require('electron-is-dev');
const isDevelopment = require('electron-is-dev');
let environment;
// In production mode, NODE_ENV cannot be customized by the user
if (electronIsDev) {
if (isDevelopment) {
environment = process.env.NODE_ENV || 'development';
process.env.LOKI_DEV = 1;
} else {
environment = 'production';
}
@ -18,12 +19,14 @@ process.env.NODE_CONFIG_DIR = path.join(__dirname, '..', 'config');
if (environment === 'production') {
// harden production config against the local env
process.env.NODE_CONFIG = '';
process.env.NODE_CONFIG_STRICT_MODE = true;
process.env.NODE_CONFIG_STRICT_MODE = !isDevelopment;
process.env.HOSTNAME = '';
process.env.ALLOW_CONFIG_MUTATIONS = '';
process.env.SUPPRESS_NO_CONFIG_WARNING = '';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '';
if (!process.env.LOKI_DEV) {
// We could be running againt production but still be in dev mode, we need to handle that
if (!isDevelopment) {
process.env.NODE_APP_INSTANCE = '';
}
}
@ -34,16 +37,10 @@ const config = require('config');
config.environment = environment;
// Log resulting env vars in use by config
[
'NODE_ENV',
'NODE_CONFIG_DIR',
'NODE_CONFIG',
'ALLOW_CONFIG_MUTATIONS',
'HOSTNAME',
'NODE_APP_INSTANCE',
'SUPPRESS_NO_CONFIG_WARNING',
].forEach(s => {
console.log(`${s} ${config.util.getEnv(s)}`);
});
['NODE_ENV', 'NODE_APP_INSTANCE', 'NODE_CONFIG_DIR', 'NODE_CONFIG'].forEach(
s => {
console.log(`${s} ${config.util.getEnv(s)}`);
}
);
module.exports = config;

@ -37,7 +37,7 @@ function initialize() {
`sql channel error with call ${callName}: ${errorForDisplay}`
);
// FIXME this line cause the test-integration to fail and we probably don't need it during test
if (!process.env.NODE_APP_INSTANCE.includes('test-integration')) {
if (!process.env.NODE_ENV.includes('test-integration')) {
event.sender.send(`${SQL_CHANNEL_KEY}-done`, jobId, errorForDisplay);
}
}

@ -1,15 +1,35 @@
const path = require('path');
const process = require('process');
const { app } = require('electron');
const { start } = require('./base_config');
const config = require('./config');
// Use separate data directory for development
if (config.has('storageProfile')) {
let storageProfile;
// Node makes sure all environment variables are strings
const { NODE_ENV: environment, NODE_APP_INSTANCE: instance } = process.env;
// We need to make sure instance is not empty
const isValidInstance = typeof instance === 'string' && instance.length > 0;
const isProduction = environment === 'production' && !isValidInstance;
// Use seperate data directories for each different environment and app instances
// We should prioritise config values first
if (config.has(storageProfile)) {
storageProfile = config.get('storageProfile');
} else if (!isProduction) {
storageProfile = environment;
if (isValidInstance) {
storageProfile = storageProfile.concat(`-${instance}`);
}
}
if (storageProfile) {
const userData = path.join(
app.getPath('appData'),
`Loki-Messenger-${config.get('storageProfile')}`
`Session-${storageProfile}`
);
app.setPath('userData', userData);

@ -1,6 +0,0 @@
{
"storageProfile": "testIntegration2Profile",
"openDevTools": false,
"updatesEnabled": false,
"localServerPort": "8082"
}

@ -3,7 +3,6 @@
"localUrl": "localhost.loki",
"cdnUrl": "random.snode",
"contentProxyUrl": "",
"localServerPort": "8081",
"defaultPoWDifficulty": "1",
"seedNodeList": [
{

@ -1,16 +0,0 @@
{
"storageProfile": "development1",
"localServerPort": "8082",
"seedNodeList": [
{
"ip": "public.loki.foundation",
"port": "38157"
},
{
"ip": "storage.testnetseed1.loki.network",
"port": "38157"
}
],
"openDevTools": true,
"defaultPublicChatServer": "https://chat-dev.lokinet.org/"
}

@ -1,16 +0,0 @@
{
"storageProfile": "development2",
"localServerPort": "8083",
"seedNodeList": [
{
"ip": "public.loki.foundation",
"port": "38157"
},
{
"ip": "storage.testnetseed1.loki.network",
"port": "38157"
}
],
"openDevTools": true,
"defaultPublicChatServer": "https://chat-dev.lokinet.org/"
}

@ -1,5 +1,4 @@
{
"storageProfile": "development",
"seedNodeList": [
{
"ip": "public.loki.foundation",

@ -1,6 +0,0 @@
{
"storageProfile": "devprod1Profile",
"localServerPort": "8082",
"openDevTools": true,
"updatesEnabled": false
}

@ -1,5 +1,4 @@
{
"storageProfile": "devprodProfile",
"openDevTools": true,
"updatesEnabled": false
}

@ -0,0 +1,4 @@
{
"openDevTools": true,
"updatesEnabled": false
}

@ -1,4 +0,0 @@
{
"storageProfile": "staging",
"openDevTools": true
}

@ -1,5 +1,4 @@
{
"storageProfile": "swarm-testing",
"seedNodeList": [
{
"ip": "localhost",

@ -1,11 +0,0 @@
{
"storageProfile": "swarm-testing2",
"seedNodeList": [
{
"ip": "localhost",
"port": "22129"
}
],
"openDevTools": true,
"defaultPublicChatServer": "https://team-chat.lokinet.org/"
}

@ -1,5 +1,4 @@
{
"storageProfile": "testIntegrationProfile",
"openDevTools": false,
"updatesEnabled": false
}

@ -50,14 +50,18 @@ module.exports = {
return new Promise(resolve => setTimeout(resolve, ms));
},
async startApp(env = 'test-integration-session') {
async startApp(environment = 'test-integration-session') {
const env = environment.startsWith('test-integration')
? 'test-integration'
: environment;
const instance = environment.replace('test-integration-', '');
const app1 = new Application({
path: path.join(__dirname, '..', 'node_modules', '.bin', 'electron'),
args: ['.'],
env: {
NODE_APP_INSTANCE: env,
NODE_ENV: 'production',
LOKI_DEV: 1,
NODE_ENV: env,
NODE_APP_INSTANCE: instance,
USE_STUBBED_NETWORK: true,
ELECTRON_ENABLE_LOGGING: true,
ELECTRON_ENABLE_STACK_DUMPING: true,
@ -122,12 +126,7 @@ module.exports = {
},
async startAndAssureCleanedApp(env = 'test-integration-session') {
const prefix = 'test-integration-session-';
const envNumber = env.substr(env.lastIndexOf(prefix) + prefix.length) || '';
const userData = path.join(
this.USER_DATA_ROOT_FOLDER,
`Loki-Messenger-testIntegration${envNumber}Profile`
);
const userData = path.join(this.USER_DATA_ROOT_FOLDER, `Session-${env}`);
await this.rmFolder(userData);

@ -155,7 +155,6 @@ function prepareURL(pathSegments, moreKeys) {
serverUrl: config.get('serverUrl'),
localUrl: config.get('localUrl'),
cdnUrl: config.get('cdnUrl'),
localServerPort: config.get('localServerPort'),
defaultPoWDifficulty: config.get('defaultPoWDifficulty'),
seedNodeList: JSON.stringify(config.get('seedNodeList')),
certificateAuthority: config.get('certificateAuthority'),
@ -900,7 +899,7 @@ app.on('window-all-closed', () => {
config.environment === 'test' ||
config.environment === 'test-lib' ||
config.environment === 'test-loki' ||
config.environmen.includes('test-integration')
config.environment.includes('test-integration')
) {
app.quit();
}
@ -951,11 +950,10 @@ ipc.on('add-setup-menu-items', () => {
});
ipc.on('draw-attention', () => {
if (process.platform === 'darwin') {
app.dock.bounce();
} else if (process.platform === 'win32') {
mainWindow.flashFrame(true);
} else if (process.platform === 'linux') {
if (!mainWindow) {
return;
}
if (process.platform === 'win32' || process.platform === 'linux') {
mainWindow.flashFrame(true);
}
});

@ -18,48 +18,39 @@
"start": "electron .",
"start-multi": "cross-env NODE_APP_INSTANCE=1 electron .",
"start-multi2": "cross-env NODE_APP_INSTANCE=2 electron .",
"start-prod": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod LOKI_DEV=1 electron .",
"start-prod-multi": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod1 LOKI_DEV=1 electron .",
"start-swarm-test": "cross-env NODE_ENV=swarm-testing NODE_APP_INSTANCE=test1 LOKI_DEV=1 electron .",
"start-swarm-test-2": "cross-env NODE_ENV=swarm-testing2 NODE_APP_INSTANCE=test2 LOKI_DEV=1 electron .",
"start-prod": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod electron .",
"start-prod-multi": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod1 electron .",
"start-swarm-test": "cross-env NODE_ENV=swarm-testing NODE_APP_INSTANCE=1 electron .",
"start-swarm-test-2": "cross-env NODE_ENV=swarm-testing NODE_APP_INSTANCE=2 electron .",
"grunt": "grunt",
"icon-gen": "electron-icon-maker --input=images/icon_1024.png --output=./build",
"generate": "yarn icon-gen && yarn grunt",
"build": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV",
"build-release": "cross-env SIGNAL_ENV=production npm run build -- --config.directories.output=release",
"make:linux:x64:appimage": "electron-builder build --linux appimage --x64",
"build-module-protobuf": "pbjs --target static-module --wrap commonjs --out ts/protobuf/compiled.js protos/*.proto && pbts --out ts/protobuf/compiled.d.ts ts/protobuf/compiled.js",
"clean-module-protobuf": "rm -f ts/protobuf/compiled.d.ts ts/protobuf/compiled.js",
"build-protobuf": "yarn build-module-protobuf",
"clean-protobuf": "yarn clean-module-protobuf",
"prepare-beta-build": "node prepare_beta_build.js",
"prepare-import-build": "node prepare_import_build.js",
"publish-to-apt": "NAME=$npm_package_name VERSION=$npm_package_version ./aptly.sh",
"test": "yarn test-node && yarn test-electron",
"test-view": "NODE_ENV=test yarn run start",
"test-lib-view": "NODE_ENV=test-lib yarn run start",
"test-loki-view": "NODE_ENV=test-loki yarn run start",
"test-electron": "yarn grunt test",
"test-integration-session": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 5000 integration_test/integration_test.js",
"test-integration": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 5000 integration_test/integration_test.js",
"test-node": "mocha --recursive --exit test/app test/modules ts/test libloki/test/node",
"test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test libloki/test/node",
"test-node-coverage-html": "nyc --reporter=lcov --reporter=html mocha --recursive test/a/* */pp test/modules ts/test libloki/test/node",
"eslint": "eslint --cache .",
"eslint-fix": "eslint --fix .",
"eslint-full": "eslint .",
"lint": "yarn format --list-different && yarn lint-windows",
"lint-full": "yarn format-full --list-different; yarn lint-windows-full",
"dev-lint": "yarn format --list-different; yarn lint-windows",
"lint-windows": "yarn eslint && yarn tslint",
"lint-windows-full": "yarn eslint-full && yarn tslint",
"lint": "yarn format && yarn lint-files",
"lint-full": "yarn format-full && yarn lint-files-full",
"dev-lint": "yarn format && yarn lint-files",
"lint-files": "yarn eslint && yarn tslint",
"lint-files-full": "yarn eslint-full && yarn tslint",
"lint-deps": "node ts/util/lint/linter.js",
"tslint": "tslint --format stylish --project .",
"format": "prettier --write `git ls-files --modified *.{css,js,json,md,scss,ts,tsx}` `git ls-files --modified ./**/*.{css,js,json,md,scss,ts,tsx}`",
"format-full": "prettier --write \"*.{css,js,json,md,scss,ts,tsx}\" \"./**/*.{css,js,json,md,scss,ts,tsx}\"",
"format": "prettier --list-different --write `git ls-files --modified *.{css,js,json,md,scss,ts,tsx}` `git ls-files --modified ./**/*.{css,js,json,md,scss,ts,tsx}`",
"format-full": "prettier --list-different --write \"*.{css,js,json,md,scss,ts,tsx}\" \"./**/*.{css,js,json,md,scss,ts,tsx}\"",
"transpile": "tsc",
"clean-transpile": "rimraf ts/**/*.js && rimraf ts/*.js",
"open-coverage": "open coverage/lcov-report/index.html",
"styleguide": "styleguidist server",
"pow-metrics": "node metrics_app.js localhost 9000",
"ready": "yarn clean-transpile && yarn grunt && yarn lint-full && yarn test-node && yarn test-electron && yarn lint-deps"
},

@ -52,8 +52,8 @@ window.getDefaultFileServer = () => config.defaultFileServer;
window.initialisedAPI = false;
if (
typeof process.env.NODE_APP_INSTANCE === 'string' &&
process.env.NODE_APP_INSTANCE.includes('test-integration')
typeof process.env.NODE_ENV === 'string' &&
process.env.NODE_ENV.includes('test-integration')
) {
window.electronRequire = require;
}
@ -317,8 +317,6 @@ window.LokiFileServerAPI = require('./js/modules/loki_file_server_api');
window.LokiRssAPI = require('./js/modules/loki_rss_api');
window.localServerPort = config.localServerPort;
window.mnemonic = require('./libloki/modules/mnemonic');
const WorkerInterface = require('./js/modules/util_worker_interface');

@ -1,66 +0,0 @@
/* eslint-disable no-console */
const fs = require('fs');
const _ = require('lodash');
const packageJson = require('./package.json');
const { version } = packageJson;
const beta = /beta/;
// You might be wondering why this file is necessary. It comes down to our desire to allow
// side-by-side installation of production and beta builds. Electron-Builder uses
// top-level data from package.json for many things, like the executable name, the
// debian package name, the install directory under /opt on linux, etc. We tried
// adding the ${channel} macro to these values, but Electron-Builder didn't like that.
if (!beta.test(version)) {
process.exit();
}
console.log('prepare_beta_build: updating package.json');
// -------
const NAME_PATH = 'name';
const PRODUCTION_NAME = 'loki-messenger-desktop';
const BETA_NAME = 'loki-messenger-desktop-beta';
const PRODUCT_NAME_PATH = 'productName';
const PRODUCTION_PRODUCT_NAME = 'Session';
const BETA_PRODUCT_NAME = 'Session Beta';
const APP_ID_PATH = 'build.appId';
const PRODUCTION_APP_ID = 'com.loki-project.messenger-desktop';
const BETA_APP_ID = 'com.loki-project.messenger-desktop-beta';
const STARTUP_WM_CLASS_PATH = 'build.linux.desktop.StartupWMClass';
const PRODUCTION_STARTUP_WM_CLASS = 'Session';
const BETA_STARTUP_WM_CLASS = 'Session Beta';
// -------
function checkValue(object, objectPath, expected) {
const actual = _.get(object, objectPath);
if (actual !== expected) {
throw new Error(`${objectPath} was ${actual}; expected ${expected}`);
}
}
// ------
checkValue(packageJson, NAME_PATH, PRODUCTION_NAME);
checkValue(packageJson, PRODUCT_NAME_PATH, PRODUCTION_PRODUCT_NAME);
checkValue(packageJson, APP_ID_PATH, PRODUCTION_APP_ID);
checkValue(packageJson, STARTUP_WM_CLASS_PATH, PRODUCTION_STARTUP_WM_CLASS);
// -------
_.set(packageJson, NAME_PATH, BETA_NAME);
_.set(packageJson, PRODUCT_NAME_PATH, BETA_PRODUCT_NAME);
_.set(packageJson, APP_ID_PATH, BETA_APP_ID);
_.set(packageJson, STARTUP_WM_CLASS_PATH, BETA_STARTUP_WM_CLASS);
// -------
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, ' '));

@ -1,69 +0,0 @@
/* eslint-disable no-console */
const fs = require('fs');
const _ = require('lodash');
const packageJson = require('./package.json');
const defaultConfig = require('./config/default.json');
function checkValue(object, objectPath, expected) {
const actual = _.get(object, objectPath);
if (actual !== expected) {
throw new Error(`${objectPath} was ${actual}; expected ${expected}`);
}
}
// You might be wondering why this file is necessary. We have some very specific
// requirements around our import-flavor builds. They need to look exactly the same as
// normal builds, but they must immediately open into import mode. So they need a
// slight config tweak, and then a change to the .app/.exe name (note: we do NOT want to
// change where data is stored or anything, since that would make these builds
// incompatible with the mainline builds) So we just change the artifact name.
//
// Another key thing to know about these builds is that we should not upload the
// latest.yml (windows) and latest-mac.yml (mac) that go along with the executables.
// This would interrupt the normal install flow for users installing from
// signal.org/download. So any release script will need to upload these files manually
// instead of relying on electron-builder, which will upload everything.
// -------
console.log('prepare_import_build: updating config/default.json');
const IMPORT_PATH = 'import';
const IMPORT_START_VALUE = false;
const IMPORT_END_VALUE = true;
checkValue(defaultConfig, IMPORT_PATH, IMPORT_START_VALUE);
_.set(defaultConfig, IMPORT_PATH, IMPORT_END_VALUE);
// -------
console.log('prepare_import_build: updating package.json');
const MAC_ASSET_PATH = 'build.mac.artifactName';
// eslint-disable-next-line no-template-curly-in-string
const MAC_ASSET_START_VALUE = '${name}-mac-${version}.${ext}';
// eslint-disable-next-line no-template-curly-in-string
const MAC_ASSET_END_VALUE = '${name}-mac-${version}-import.${ext}';
const WIN_ASSET_PATH = 'build.win.artifactName';
// eslint-disable-next-line no-template-curly-in-string
const WIN_ASSET_START_VALUE = '${name}-win-${version}.${ext}';
// eslint-disable-next-line no-template-curly-in-string
const WIN_ASSET_END_VALUE = '${name}-win-${version}-import.${ext}';
checkValue(packageJson, MAC_ASSET_PATH, MAC_ASSET_START_VALUE);
checkValue(packageJson, WIN_ASSET_PATH, WIN_ASSET_START_VALUE);
_.set(packageJson, MAC_ASSET_PATH, MAC_ASSET_END_VALUE);
_.set(packageJson, WIN_ASSET_PATH, WIN_ASSET_END_VALUE);
// ---
fs.writeFileSync(
'./config/default.json',
JSON.stringify(defaultConfig, null, ' ')
);
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, ' '));
Loading…
Cancel
Save