Extract environment config initialisation to server-core

Summary: This diff makes most stuff that is read from the `os` package, and version info etc available from the `serverConfig` object, so that flipper-ui-core no longer needs the `os` package.

Reviewed By: passy

Differential Revision: D32694848

fbshipit-source-id: 93af1e95d898da9aaf351a6970b5a7652ee835c8
This commit is contained in:
Michel Weststrate
2021-12-08 04:25:28 -08:00
committed by Facebook GitHub Bot
parent de59bbedd2
commit 2a4fe77404
22 changed files with 199 additions and 135 deletions

View File

@@ -20,6 +20,7 @@ import type {RenderHost} from 'flipper-ui-core';
import os from 'os'; import os from 'os';
import { import {
FlipperServerImpl, FlipperServerImpl,
getEnvironmentInfo,
getGatekeepers, getGatekeepers,
loadLauncherSettings, loadLauncherSettings,
loadProcessConfig, loadProcessConfig,
@@ -30,6 +31,7 @@ import {
getLogger, getLogger,
isTest, isTest,
Logger, Logger,
parseEnvironmentVariables,
setLoggerInstance, setLoggerInstance,
Settings, Settings,
} from 'flipper-common'; } from 'flipper-common';
@@ -61,9 +63,10 @@ async function start() {
const app = remote.app; const app = remote.app;
const execPath = process.execPath || remote.process.execPath; const execPath = process.execPath || remote.process.execPath;
const appPath = app.getAppPath(); const appPath = app.getAppPath();
const staticPath = getStaticDir();
const isProduction = !/node_modules[\\/]electron[\\/]/.test(execPath); const isProduction = !/node_modules[\\/]electron[\\/]/.test(execPath);
const env = process.env; const env = process.env;
const environmentInfo = await getEnvironmentInfo(staticPath, isProduction);
const logger = createDelegatedLogger(); const logger = createDelegatedLogger();
setLoggerInstance(logger); setLoggerInstance(logger);
@@ -80,14 +83,15 @@ async function start() {
const flipperServer = new FlipperServerImpl( const flipperServer = new FlipperServerImpl(
{ {
env, environmentInfo,
gatekeepers: getGatekeepers(), env: parseEnvironmentVariables(env),
isProduction, // TODO: make userame parameterizable
gatekeepers: getGatekeepers(environmentInfo.os.unixname),
paths: { paths: {
appPath, appPath,
homePath: app.getPath('home'), homePath: app.getPath('home'),
execPath, execPath,
staticPath: getStaticDir(), staticPath,
tempPath: app.getPath('temp'), tempPath: app.getPath('temp'),
desktopPath: app.getPath('desktop'), desktopPath: app.getPath('desktop'),
}, },

View File

@@ -16,7 +16,12 @@ import {
OS as PluginOS, OS as PluginOS,
UpdatablePluginDetails, UpdatablePluginDetails,
} from './PluginDetails'; } from './PluginDetails';
import {LauncherSettings, ProcessConfig, Settings} from './settings'; import {
EnvironmentInfo,
LauncherSettings,
ProcessConfig,
Settings,
} from './settings';
// In the future, this file would deserve it's own package, as it doesn't really relate to plugins. // In the future, this file would deserve it's own package, as it doesn't really relate to plugins.
// Since flipper-plugin however is currently shared among server, client and defines a lot of base types, leaving it here for now. // Since flipper-plugin however is currently shared among server, client and defines a lot of base types, leaving it here for now.
@@ -177,13 +182,38 @@ export type FlipperServerCommands = {
'plugins-remove-plugins': (names: string[]) => Promise<void>; 'plugins-remove-plugins': (names: string[]) => Promise<void>;
}; };
export type ENVIRONMENT_VARIABLES = /**
| 'NODE_ENV' * White listed environment variables that can be used in Flipper UI / plugins
| 'DEV_SERVER_URL' */
| 'CONFIG' const environmentVariables = {
| 'FLIPPER_ENABLED_PLUGINS' NODE_ENV: 1,
| 'FB_ONDEMAND' DEV_SERVER_URL: 1,
| 'FLIPPER_INTERNGRAPH_URL'; CONFIG: 1,
FLIPPER_ENABLED_PLUGINS: 1,
FB_ONDEMAND: 1,
FLIPPER_INTERNGRAPH_URL: 1,
JEST_WORKER_ID: 1,
FLIPPER_DOCS_BASE_URL: 1,
FLIPPER_NO_PLUGIN_AUTO_UPDATE: 1,
FLIPPER_NO_PLUGIN_MARKETPLACE: 1,
HOME: 1,
METRO_PORT_ENV_VAR: 1,
} as const;
export type ENVIRONMENT_VARIABLES = keyof typeof environmentVariables;
/**
* Grab all environment variables from a process.env object, without leaking variables which usage isn't declared in ENVIRONMENT_VARIABLES
*/
export function parseEnvironmentVariables(
baseEnv: any,
): Partial<Record<ENVIRONMENT_VARIABLES, string>> {
const result: any = {};
Object.keys(environmentVariables).forEach((k) => {
result[k] = baseEnv[k];
});
return result;
}
type ENVIRONMENT_PATHS = type ENVIRONMENT_PATHS =
| 'appPath' | 'appPath'
@@ -194,7 +224,6 @@ type ENVIRONMENT_PATHS =
| 'desktopPath'; | 'desktopPath';
export type FlipperServerConfig = { export type FlipperServerConfig = {
isProduction: boolean;
gatekeepers: Record<string, boolean>; gatekeepers: Record<string, boolean>;
env: Partial<Record<ENVIRONMENT_VARIABLES, string>>; env: Partial<Record<ENVIRONMENT_VARIABLES, string>>;
paths: Record<ENVIRONMENT_PATHS, string>; paths: Record<ENVIRONMENT_PATHS, string>;
@@ -202,6 +231,7 @@ export type FlipperServerConfig = {
launcherSettings: LauncherSettings; launcherSettings: LauncherSettings;
processConfig: ProcessConfig; processConfig: ProcessConfig;
validWebSocketOrigins: string[]; validWebSocketOrigins: string[];
environmentInfo: EnvironmentInfo;
}; };
export interface FlipperServer { export interface FlipperServer {

View File

@@ -56,7 +56,7 @@ export type LauncherSettings = {
// Settings that primarily only apply to Eelectron atm // Settings that primarily only apply to Eelectron atm
// TODO: further separte between flipper-ui config and Electron config // TODO: further separte between flipper-ui config and Electron config
export type ProcessConfig = { export type ProcessConfig = {
disabledPlugins: Set<string>; disabledPlugins: string[];
lastWindowPosition: { lastWindowPosition: {
x: number; x: number;
y: number; y: number;
@@ -68,3 +68,21 @@ export type ProcessConfig = {
// Controls whether to delegate to the launcher if present. // Controls whether to delegate to the launcher if present.
launcherEnabled: boolean; launcherEnabled: boolean;
}; };
export type EnvironmentInfo = {
processId: number;
isProduction: boolean;
releaseChannel: ReleaseChannel;
flipperReleaseRevision?: string;
appVersion: string;
os: {
arch: string;
platform: string;
unixname: string;
};
versions: {
electron?: string;
node: string;
platform: string;
};
};

View File

@@ -12,6 +12,7 @@ import os from 'os';
import yargs from 'yargs'; import yargs from 'yargs';
import { import {
FlipperServerImpl, FlipperServerImpl,
getEnvironmentInfo,
loadLauncherSettings, loadLauncherSettings,
loadProcessConfig, loadProcessConfig,
loadSettings, loadSettings,
@@ -21,6 +22,7 @@ import {
Logger, Logger,
DeviceDescription, DeviceDescription,
setLoggerInstance, setLoggerInstance,
parseEnvironmentVariables,
} from 'flipper-common'; } from 'flipper-common';
import path from 'path'; import path from 'path';
import {stdout} from 'process'; import {stdout} from 'process';
@@ -54,6 +56,7 @@ const argv = yargs
async function start(deviceTitle: string, appName: string, pluginId: string) { async function start(deviceTitle: string, appName: string, pluginId: string) {
return new Promise(async (_resolve, reject) => { return new Promise(async (_resolve, reject) => {
const staticPath = path.resolve(__dirname, '..', '..', 'static');
let device: DeviceDescription | undefined; let device: DeviceDescription | undefined;
let deviceResolver: () => void; let deviceResolver: () => void;
const devicePromise: Promise<void> = new Promise((resolve) => { const devicePromise: Promise<void> = new Promise((resolve) => {
@@ -68,15 +71,16 @@ async function start(deviceTitle: string, appName: string, pluginId: string) {
console.debug = () => {}; console.debug = () => {};
console.info = console.error; console.info = console.error;
const environmentInfo = await getEnvironmentInfo(staticPath, false);
// TODO: initialise FB user manager to be able to do certificate exchange // TODO: initialise FB user manager to be able to do certificate exchange
const server = new FlipperServerImpl( const server = new FlipperServerImpl(
{ {
env: process.env, environmentInfo,
env: parseEnvironmentVariables(process.env),
gatekeepers: {}, gatekeepers: {},
isProduction: false,
paths: { paths: {
staticPath: path.resolve(__dirname, '..', '..', 'static'), staticPath,
tempPath: os.tmpdir(), tempPath: os.tmpdir(),
appPath: `/dev/null`, appPath: `/dev/null`,
homePath: `/dev/null`, homePath: `/dev/null`,

View File

@@ -30,7 +30,7 @@ export function loadDistilleryGK(
} }
export default class GK { export default class GK {
static init() {} static init(_username: string) {}
static get(id: GKID): boolean { static get(id: GKID): boolean {
if (process.env.NODE_ENV === 'test' && id === TEST_PASSING_GK) { if (process.env.NODE_ENV === 'test' && id === TEST_PASSING_GK) {

View File

@@ -11,16 +11,17 @@ export {FlipperServerImpl} from './FlipperServerImpl';
export {loadSettings} from './utils/settings'; export {loadSettings} from './utils/settings';
export {loadLauncherSettings} from './utils/launcherSettings'; export {loadLauncherSettings} from './utils/launcherSettings';
export {loadProcessConfig} from './utils/processConfig'; export {loadProcessConfig} from './utils/processConfig';
export {getEnvironmentInfo} from './utils/environmentInfo';
import GKImplementation from './fb-stubs/GK'; import GKImplementation from './fb-stubs/GK';
export {setupPrefetcher} from './fb-stubs/Prefetcher'; export {setupPrefetcher} from './fb-stubs/Prefetcher';
let loaded = false; let loaded = false;
export function getGatekeepers(): Record<string, boolean> { export function getGatekeepers(username: string): Record<string, boolean> {
if (!loaded) { if (!loaded) {
// this starts fetching gatekeepers, note that they will only be available on next restart! // this starts fetching gatekeepers, note that they will only be available on next restart!
GKImplementation.init(); GKImplementation.init(username);
loaded = true; loaded = true;
} }
return GKImplementation.allGKs(); return GKImplementation.allGKs();

View File

@@ -21,7 +21,7 @@ test('config is decoded from env', () => {
}); });
expect(config).toEqual({ expect(config).toEqual({
disabledPlugins: new Set(['pluginA', 'pluginB', 'pluginC']), disabledPlugins: ['pluginA', 'pluginB', 'pluginC'],
lastWindowPosition: {x: 4, y: 8, width: 15, height: 16}, lastWindowPosition: {x: 4, y: 8, width: 15, height: 16},
launcherMsg: 'wubba lubba dub dub', launcherMsg: 'wubba lubba dub dub',
screenCapturePath: '/my/screenshot/path', screenCapturePath: '/my/screenshot/path',
@@ -31,7 +31,7 @@ test('config is decoded from env', () => {
test('config is decoded from env with defaults', () => { test('config is decoded from env with defaults', () => {
expect(loadProcessConfig({CONFIG: '{}'})).toEqual({ expect(loadProcessConfig({CONFIG: '{}'})).toEqual({
disabledPlugins: new Set([]), disabledPlugins: [],
lastWindowPosition: undefined, lastWindowPosition: undefined,
launcherMsg: undefined, launcherMsg: undefined,
screenCapturePath: undefined, screenCapturePath: undefined,

View File

@@ -0,0 +1,57 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import os from 'os';
import fs from 'fs-extra';
import path from 'path';
import {EnvironmentInfo, ReleaseChannel} from 'flipper-common';
export async function getEnvironmentInfo(
staticPath: string,
isProduction: boolean,
): Promise<EnvironmentInfo> {
const packageJson = await fs.readJSON(
path.resolve(staticPath, 'package.json'),
);
const releaseChannel: ReleaseChannel =
process.env.FLIPPER_RELEASE_CHANNEL === 'insiders'
? ReleaseChannel.INSIDERS
: process.env.FLIPPER_RELEASE_CHANNEL === 'stable'
? ReleaseChannel.STABLE
: packageJson.releaseChannel === 'insiders'
? ReleaseChannel.INSIDERS
: ReleaseChannel.STABLE;
// This is provided as part of the bundling process for headless.
const flipperReleaseRevision =
(global as any).__REVISION__ ?? packageJson.revision;
const appVersion =
process.env.FLIPPER_FORCE_VERSION ??
(isProduction ? packageJson.version : '0.0.0');
return {
processId: process.pid,
isProduction,
releaseChannel,
flipperReleaseRevision,
appVersion,
os: {
arch: process.arch,
platform: process.platform,
unixname: os.userInfo().username,
},
versions: {
electron: process.versions.electron,
node: process.versions.node,
platform: os.release(),
},
};
}

View File

@@ -12,7 +12,7 @@ import {ProcessConfig} from 'flipper-common';
export function loadProcessConfig(env: NodeJS.ProcessEnv): ProcessConfig { export function loadProcessConfig(env: NodeJS.ProcessEnv): ProcessConfig {
const json = JSON.parse(env.CONFIG || '{}'); const json = JSON.parse(env.CONFIG || '{}');
return { return {
disabledPlugins: new Set<string>(json.disabledPlugins || []), disabledPlugins: json.disabledPlugins || [],
lastWindowPosition: json.lastWindowPosition, lastWindowPosition: json.lastWindowPosition,
launcherMsg: json.launcherMsg, launcherMsg: json.launcherMsg,
screenCapturePath: json.screenCapturePath, screenCapturePath: json.screenCapturePath,

View File

@@ -9,13 +9,13 @@
import chalk from 'chalk'; import chalk from 'chalk';
import path from 'path'; import path from 'path';
import {startFlipperServer} from './startFlipperServer';
import {startBaseServer} from './startBaseServer';
import {startSocketServer} from './startSocketServer';
// TODO: currently flipper-server is only suitable for development, // TODO: currently flipper-server is only suitable for development,
// needs to be come independently runnable, prebundled, distributed, etc! // needs to be come independently runnable, prebundled, distributed, etc!
// in future require conditionally // in future require conditionally
import {startWebServerDev} from './startWebServerDev'; import {startWebServerDev} from './startWebServerDev';
import {startFlipperServer} from './startFlipperServer';
import {startBaseServer} from './startBaseServer';
import {startSocketServer} from './startSocketServer';
const PORT = 52342; const PORT = 52342;
const rootDir = path.resolve(__dirname, '..', '..'); const rootDir = path.resolve(__dirname, '..', '..');

View File

@@ -14,9 +14,10 @@ import {
loadLauncherSettings, loadLauncherSettings,
loadProcessConfig, loadProcessConfig,
loadSettings, loadSettings,
getEnvironmentInfo,
} from 'flipper-server-core'; } from 'flipper-server-core';
import { import {
ENVIRONMENT_VARIABLES, parseEnvironmentVariables,
isTest, isTest,
Logger, Logger,
setLoggerInstance, setLoggerInstance,
@@ -26,7 +27,7 @@ import fs from 'fs';
export async function startFlipperServer( export async function startFlipperServer(
rootDir: string, rootDir: string,
staticDir: string, staticPath: string,
): Promise<FlipperServerImpl> { ): Promise<FlipperServerImpl> {
if (os.platform() === 'darwin') { if (os.platform() === 'darwin') {
// By default Node.JS has its internal certificate storage and doesn't use // By default Node.JS has its internal certificate storage and doesn't use
@@ -57,7 +58,7 @@ export async function startFlipperServer(
try { try {
if (!isTest()) { if (!isTest()) {
keytar = require(path.join( keytar = require(path.join(
staticDir, staticPath,
'native-modules', 'native-modules',
`keytar-${process.platform}.node`, `keytar-${process.platform}.node`,
)); ));
@@ -66,20 +67,19 @@ export async function startFlipperServer(
console.error('Failed to load keytar:', e); console.error('Failed to load keytar:', e);
} }
const envVars: Partial<Record<ENVIRONMENT_VARIABLES, string | undefined>> = const environmentInfo = await getEnvironmentInfo(staticPath, isProduction);
Object.fromEntries(
([] as ENVIRONMENT_VARIABLES[]).map((v) => [v, process.env[v]] as const),
);
const flipperServer = new FlipperServerImpl( const flipperServer = new FlipperServerImpl(
{ {
env: envVars, environmentInfo,
gatekeepers: getGatekeepers(), env: parseEnvironmentVariables(process.env),
isProduction, // TODO: make userame parameterizable
gatekeepers: getGatekeepers(environmentInfo.os.unixname),
paths: { paths: {
appPath, appPath,
homePath: os.homedir(), homePath: os.homedir(),
execPath, execPath,
staticPath: staticDir, staticPath: staticPath,
tempPath: os.tmpdir(), tempPath: os.tmpdir(),
desktopPath: desktopPath, desktopPath: desktopPath,
}, },

View File

@@ -8,15 +8,13 @@
*/ */
import {FlipperServer, FlipperServerConfig} from 'flipper-common'; import {FlipperServer, FlipperServerConfig} from 'flipper-common';
import {getRenderHostInstance} from 'flipper-ui-core'; import {getRenderHostInstance, RenderHost} from 'flipper-ui-core';
export function initializeRenderHost( export function initializeRenderHost(
flipperServer: FlipperServer, flipperServer: FlipperServer,
flipperServerConfig: FlipperServerConfig, flipperServerConfig: FlipperServerConfig,
) { ) {
window.FlipperRenderHostInstance = { window.FlipperRenderHostInstance = {
processId: 0,
isProduction: window.flipperConfig.debug !== true,
readTextFromClipboard() { readTextFromClipboard() {
// TODO: // TODO:
return undefined; return undefined;
@@ -72,7 +70,7 @@ export function initializeRenderHost(
// eslint-disable-next-line no-eval // eslint-disable-next-line no-eval
return eval(source); return eval(source);
}, },
}; } as RenderHost;
} }
function getDefaultPluginsIndex() { function getDefaultPluginsIndex() {

View File

@@ -44,8 +44,6 @@ type ChildProcessEvents = {
* Utilities provided by the render host, e.g. Electron, the Browser, etc * Utilities provided by the render host, e.g. Electron, the Browser, etc
*/ */
export interface RenderHost { export interface RenderHost {
readonly processId: number;
readonly isProduction: boolean;
readTextFromClipboard(): string | undefined; readTextFromClipboard(): string | undefined;
writeTextToClipboard(text: string): void; writeTextToClipboard(text: string): void;
/** /**

View File

@@ -77,7 +77,7 @@ test('checkDisabled', () => {
try { try {
hostConfig.processConfig = { hostConfig.processConfig = {
...orig, ...orig,
disabledPlugins: new Set([disabledPlugin]), disabledPlugins: [disabledPlugin],
}; };
const disabled = checkDisabled([]); const disabled = checkDisabled([]);

View File

@@ -210,7 +210,7 @@ export const checkDisabled = (
config.env.FLIPPER_ENABLED_PLUGINS.split(','), config.env.FLIPPER_ENABLED_PLUGINS.split(','),
); );
} }
disabledList = config.processConfig.disabledPlugins; disabledList = new Set(config.processConfig.disabledPlugins);
} catch (e) { } catch (e) {
console.error('Failed to compute enabled/disabled plugins', e); console.error('Failed to compute enabled/disabled plugins', e);
} }

View File

@@ -95,7 +95,8 @@ export default (store: Store, logger: Logger) => {
const oldExitData = loadExitData(); const oldExitData = loadExitData();
if (oldExitData) { if (oldExitData) {
const isReload = renderHost.processId === oldExitData.pid; const isReload =
renderHost.serverConfig.environmentInfo.processId === oldExitData.pid;
const timeSinceLastStartup = const timeSinceLastStartup =
Date.now() - parseInt(oldExitData.lastSeen, 10); Date.now() - parseInt(oldExitData.lastSeen, 10);
// console.log(isReload ? 'reload' : 'restart', oldExitData); // console.log(isReload ? 'reload' : 'restart', oldExitData);
@@ -370,7 +371,7 @@ export function persistExitData(
? deconstructClientId(state.selectedAppId).app ? deconstructClientId(state.selectedAppId).app
: '', : '',
cleanExit, cleanExit,
pid: getRenderHostInstance().processId, pid: getRenderHostInstance().serverConfig.environmentInfo.processId,
}; };
window.localStorage.setItem( window.localStorage.setItem(
flipperExitDataKey, flipperExitDataKey,

View File

@@ -1,15 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {readCurrentRevision} from '../packageMetadata';
test('readCurrentRevision does not return something meaningful in dev mode', async () => {
const ret = await readCurrentRevision();
expect(ret).toBeUndefined();
});

View File

@@ -23,7 +23,6 @@ import {default as BaseDevice} from '../devices/BaseDevice';
import {default as ArchivedDevice} from '../devices/ArchivedDevice'; import {default as ArchivedDevice} from '../devices/ArchivedDevice';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {v4 as uuidv4} from 'uuid'; import {v4 as uuidv4} from 'uuid';
import {readCurrentRevision} from './packageMetadata';
import {tryCatchReportPlatformFailures} from 'flipper-common'; import {tryCatchReportPlatformFailures} from 'flipper-common';
import {TestIdler} from './Idler'; import {TestIdler} from './Idler';
import {setStaticView} from '../reducers/connections'; import {setStaticView} from '../reducers/connections';
@@ -243,7 +242,8 @@ async function addSaltToDeviceSerial({
} }
return {...notif, client: notif.client.replace(serial, newSerial)}; return {...notif, client: notif.client.replace(serial, newSerial)};
}); });
const revision: string | undefined = await readCurrentRevision(); const revision: string | undefined =
getRenderHostInstance().serverConfig.environmentInfo.flipperReleaseRevision;
return { return {
fileVersion: getAppVersion() || 'unknown', fileVersion: getAppVersion() || 'unknown',
flipperReleaseRevision: revision, flipperReleaseRevision: revision,

View File

@@ -10,13 +10,10 @@
// Use of sync methods is cached. // Use of sync methods is cached.
/* eslint-disable node/no-sync */ /* eslint-disable node/no-sync */
import os from 'os';
import isProduction from './isProduction';
import fs from 'fs-extra';
import {getStaticPath} from './pathUtils';
import type {State, Store} from '../reducers/index'; import type {State, Store} from '../reducers/index';
import {sideEffect} from './sideEffect'; import {sideEffect} from './sideEffect';
import {Logger, isTest, deconstructClientId} from 'flipper-common'; import {Logger, deconstructClientId} from 'flipper-common';
import {getRenderHostInstance} from '../RenderHost';
type PlatformInfo = { type PlatformInfo = {
arch: string; arch: string;
@@ -83,15 +80,13 @@ export default (store: Store, _logger: Logger) => {
*/ */
export function getInfo(): Info { export function getInfo(): Info {
if (!platformInfo) { if (!platformInfo) {
const envInfo = getRenderHostInstance().serverConfig.environmentInfo;
platformInfo = { platformInfo = {
arch: process.arch, arch: envInfo.os.arch,
platform: process.platform, platform: envInfo.os.platform,
unixname: os.userInfo().username, unixname: envInfo.os.unixname,
versions: { versions: envInfo.versions,
electron: process.versions.electron,
node: process.versions.node,
platform: os.release(),
},
}; };
} }
return { return {
@@ -100,18 +95,8 @@ export function getInfo(): Info {
}; };
} }
let APP_VERSION: string | undefined;
export function getAppVersion(): string { export function getAppVersion(): string {
return (APP_VERSION = return getRenderHostInstance().serverConfig.environmentInfo.appVersion;
APP_VERSION ??
process.env.FLIPPER_FORCE_VERSION ??
(isTest()
? '0.0.0'
: (isProduction()
? fs.readJsonSync(getStaticPath('package.json'), {
throws: false,
})?.version
: require('../../package.json').version) ?? '0.0.0'));
} }
export function stringifyInfo(info: Info): string { export function stringifyInfo(info: Info): string {

View File

@@ -10,5 +10,5 @@
import {getRenderHostInstance} from '../RenderHost'; import {getRenderHostInstance} from '../RenderHost';
export default function isProduction() { export default function isProduction() {
return getRenderHostInstance().isProduction; return getRenderHostInstance().serverConfig.environmentInfo.isProduction;
} }

View File

@@ -1,33 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import lodash from 'lodash';
import path from 'path';
import fs from 'fs';
import {promisify} from 'util';
import {getRenderHostInstance} from '../RenderHost';
const getPackageJSON = async () => {
const base = getRenderHostInstance().serverConfig.paths.appPath;
const content = await promisify(fs.readFile)(
path.join(base, 'package.json'),
'utf-8',
);
return JSON.parse(content);
};
export const readCurrentRevision: () => Promise<string | undefined> =
lodash.memoize(async () => {
// This is provided as part of the bundling process for headless.
if (global.__REVISION__) {
return global.__REVISION__;
}
const json = await getPackageJSON();
return json.revision;
});

View File

@@ -11,16 +11,19 @@
import {cleanup} from '@testing-library/react'; import {cleanup} from '@testing-library/react';
import {resolve} from 'path'; import {resolve} from 'path';
import {tmpdir} from 'os'; import os from 'os';
window.FlipperRenderHostInstance = createStubRenderHost(); window.FlipperRenderHostInstance = createStubRenderHost();
require('../flipper-ui-core/src/fb-stubs/Logger').init(undefined, {
isTest: true,
});
import {TestUtils} from 'flipper-plugin'; import {TestUtils} from 'flipper-plugin';
import {FlipperServerConfig, ReleaseChannel, Tristate} from 'flipper-common'; import {
FlipperServerConfig,
ReleaseChannel,
Tristate,
parseEnvironmentVariables,
} from 'flipper-common';
// Only import the type!
import type {RenderHost} from 'flipper-ui-core'; import type {RenderHost} from 'flipper-ui-core';
const test = global.test; const test = global.test;
@@ -92,12 +95,27 @@ Object.defineProperty(window, 'matchMedia', {
function createStubRenderHost(): RenderHost { function createStubRenderHost(): RenderHost {
const rootPath = resolve(__dirname, '..'); const rootPath = resolve(__dirname, '..');
const stubConfig: FlipperServerConfig = { const stubConfig: FlipperServerConfig = {
env: {...process.env}, environmentInfo: {
processId: process.pid,
appVersion: '0.0.0',
isProduction: false,
releaseChannel: ReleaseChannel.DEFAULT,
flipperReleaseRevision: '000',
os: {
arch: process.arch,
platform: process.platform,
unixname: os.userInfo().username,
},
versions: {
node: process.versions.node,
platform: os.release(),
},
},
env: parseEnvironmentVariables(process.env),
gatekeepers: { gatekeepers: {
TEST_PASSING_GK: true, TEST_PASSING_GK: true,
TEST_FAILING_GK: false, TEST_FAILING_GK: false,
}, },
isProduction: false,
launcherSettings: { launcherSettings: {
ignoreLocalPin: false, ignoreLocalPin: false,
releaseChannel: ReleaseChannel.DEFAULT, releaseChannel: ReleaseChannel.DEFAULT,
@@ -108,10 +126,10 @@ function createStubRenderHost(): RenderHost {
execPath: process.execPath, execPath: process.execPath,
homePath: `/dev/null`, homePath: `/dev/null`,
staticPath: resolve(rootPath, 'static'), staticPath: resolve(rootPath, 'static'),
tempPath: tmpdir(), tempPath: os.tmpdir(),
}, },
processConfig: { processConfig: {
disabledPlugins: new Set(), disabledPlugins: [],
lastWindowPosition: null, lastWindowPosition: null,
launcherEnabled: false, launcherEnabled: false,
launcherMsg: null, launcherMsg: null,
@@ -135,8 +153,6 @@ function createStubRenderHost(): RenderHost {
}; };
return { return {
processId: -1,
isProduction: false,
readTextFromClipboard() { readTextFromClipboard() {
return ''; return '';
}, },