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

Fix emulators unwanted exit #1315

Merged
merged 4 commits into from Dec 22, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/cli/src/logger/index.ts
Expand Up @@ -332,13 +332,13 @@ export const logTask = (task: string, customChalk?: string | RnvApiChalkFn) => {

let msg = '';
if (typeof customChalk === 'string') {
msg = `${currentChalk.green(`[ task ]${_getCurrentTask()} ${task}`)}${taskCount} ${currentChalk.grey(
msg = `${currentChalk.green(`[ task ]${_getCurrentTask()}`)} ${task}${taskCount} ${currentChalk.grey(
customChalk
)}`;
} else if (customChalk) {
msg = customChalk(`[ task ]${_getCurrentTask()} ${task}${taskCount}`);
} else {
msg = currentChalk.green(`[ task ]${_getCurrentTask()} ${task}${taskCount}`);
msg = `${currentChalk.green(`[ task ]${_getCurrentTask()}`)} ${task}${taskCount}`;
}

console.log(_sanitizePaths(msg));
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/__tests__/exec.test.ts
Expand Up @@ -3,7 +3,15 @@ import { createRnvContext } from '../context';
import { generateContextDefaults } from '../context/defaults';
import { executeAsync, commandExistsSync, commandExists } from '../system/exec';

jest.mock('../logger/index.ts');
jest.mock('../logger/index.ts', () => {
return {
logTask: jest.fn(),
logDebug: jest.fn(),
chalk: () => ({
rgb: jest.fn(),
}),
};
});

describe('Testing exec functions', () => {
beforeAll(() => {
Expand Down
57 changes: 43 additions & 14 deletions packages/core/src/system/exec.ts
Expand Up @@ -14,6 +14,36 @@ import { getApi } from '../api/provider';

const { exec, execSync } = require('child_process');

const FIRE_AND_FORGET: ExecOptions = {
stdio: 'ignore', // Disable child_process output
detached: true, // Killing rnv command will NOT kill process
silent: true, // Disable spinner
shell: true, // runs `command` inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows
};

const INHERIT_OUTPUT_NO_SPINNER: ExecOptions = {
detached: false, // Killing command will kill process
silent: true, // silent: true => will not show execa spinner
stdio: 'inherit', // inherit will print during execution but no details in SUMMARY box
shell: true, // runs `command` inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows
// mono: true,
};

const SPINNER_FULL_ERROR_SUMMARY: ExecOptions = {
detached: false, // Killing command will kill process
silent: false,
stdio: 'pipe', // pipe will print final error into SUMMARY box but nothing during execution
shell: true, // runs `command` inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows
mono: false,
};

export const ExecOptionsPresets = {
// Do not await when using FIRE_AND_FORGET option
FIRE_AND_FORGET,
INHERIT_OUTPUT_NO_SPINNER,
SPINNER_FULL_ERROR_SUMMARY,
} as const;

/**
*
* Also accepts the Node's child_process exec/spawn options
Expand Down Expand Up @@ -42,11 +72,8 @@ const _execute = (c: RnvContext, command: string | Array<string>, opts: ExecOpti
mono: c.program?.mono || c.program?.json,
};

if (opts.interactive) {
defaultOpts.silent = true;
defaultOpts.stdio = 'inherit';
defaultOpts.shell = true;
}
const blue2 = chalk().rgb(50, 50, 255);

const mergedOpts = { ...defaultOpts, ...opts };

const printableEnv =
Expand All @@ -72,15 +99,14 @@ const _execute = (c: RnvContext, command: string | Array<string>, opts: ExecOpti
logMessage = replaceOverridesInString(commandAsString, privateParams, privateMask);
}

if (printableEnv) {
let logMsg = `${chalk().grey(printableEnv)} ${logMessage}`;
if (c.program.printExec) {
let logMsg = printableEnv ? `${chalk().grey(printableEnv)} ${logMessage}` : logMessage;
if (opts.cwd) {
logMsg = `cd ${opts.cwd} ${chalk().cyan('&&')} ${logMsg}`;
}
console.log(
`${chalk().green('✔')} Full exec command: ${chalk().green('>>>')}\n${logMsg}\n${chalk().green('<<<')}`
);
logRaw(`${blue2('[ exec ]')} ${blue2('<[')} ${logMsg} ${blue2(']>')}`);
}

logDebug(`_execute: ${logMessage}`);
const { silent, mono, maxErrorLength, ignoreErrors } = mergedOpts;
const spinner =
Expand All @@ -89,9 +115,9 @@ const _execute = (c: RnvContext, command: string | Array<string>, opts: ExecOpti
getApi()
.spinner({ text: `Executing: ${logMessage}` })
.start('');
if (opts.interactive) {
logRaw(`${chalk().green('✔')} Executing: ${logMessage}\n`);
}
// if (opts.interactive) {
// logRaw(`${chalk().green('✔')} Executing: ${logMessage}\n`);
// }

if (mono) {
interval = setInterval(() => {
Expand All @@ -106,7 +132,10 @@ const _execute = (c: RnvContext, command: string | Array<string>, opts: ExecOpti
} else {
child = execa.command(cleanCommand, mergedOpts);
}
c.runningProcesses.push(child);

if (!opts.detached) {
c.runningProcesses.push(child);
}

const MAX_OUTPUT_LENGTH = 200;

Expand Down
1 change: 0 additions & 1 deletion packages/core/src/system/types.ts
Expand Up @@ -8,7 +8,6 @@ export type ResolveOptions = {
};

export type ExecOptions = {
interactive?: boolean;
silent?: boolean;
stdio?: 'pipe' | 'inherit' | 'ignore';
shell?: boolean;
Expand Down
10 changes: 2 additions & 8 deletions packages/engine-rn-electron/src/sdk.ts
Expand Up @@ -37,6 +37,7 @@ import {
MACOS,
LINUX,
TASK_EXPORT,
ExecOptionsPresets,
} from '@rnv/core';
import { FileElectronPackage } from './types';
import { NpmPackageFile } from '@rnv/core/lib/configs/types';
Expand Down Expand Up @@ -364,14 +365,7 @@ const _runElectronSimulator = async (c: RnvContext) => {
}

const cmd = `node ${doResolve('electron')}/cli.js ${path.join(platformProjectDir, '/main.js')}`;
await executeAsync(c, cmd, {
interactive: true,
stdio: 'inherit',
// silent: true,
// env: {
// ...CoreEnvVars.BASE(),
// },
});
await executeAsync(c, cmd, ExecOptionsPresets.INHERIT_OUTPUT_NO_SPINNER);
};

const _generateICNS = (c: RnvContext) =>
Expand Down
6 changes: 5 additions & 1 deletion packages/engine-rn-next/src/sdk.ts
Expand Up @@ -17,6 +17,7 @@ import {
copyAssetsFolder,
RnvPlatform,
CoreEnvVars,
ExecOptionsPresets,
} from '@rnv/core';
import { getDevServerHost, openBrowser, waitForHost } from '@rnv/sdk-utils';
import { EnvVars } from './env';
Expand Down Expand Up @@ -139,6 +140,9 @@ Dev server running at: ${url}
`);

const bundleAssets = getConfigProp(c, c.platform, 'bundleAssets', false);
const opts = !c.program?.json
? ExecOptionsPresets.INHERIT_OUTPUT_NO_SPINNER
: ExecOptionsPresets.SPINNER_FULL_ERROR_SUMMARY;
return executeAsync(c, `npx next ${bundleAssets ? 'start' : 'dev'} --port ${c.runtime.port}`, {
env: {
...CoreEnvVars.BASE(),
Expand All @@ -147,7 +151,7 @@ Dev server running at: ${url}
...EnvVars.NEXT_BASE(),
...EnvVars.NODE_ENV(),
},
interactive: !c.program?.json,
...opts,
});
};

Expand Down
8 changes: 5 additions & 3 deletions packages/integration-docker/src/docker.ts
Expand Up @@ -14,6 +14,7 @@ import {
writeCleanFile,
fsExistsSync,
chalk,
ExecOptionsPresets,
} from '@rnv/core';

const rootPath = path.join(__dirname, './');
Expand Down Expand Up @@ -171,9 +172,10 @@ class Docker {
const appVersion = files.project.package.version;

logTask('docker:Dockerfile:login');
await executeAsync(`echo "${DOCKERHUB_PASS}" | docker login -u "${DOCKERHUB_USER}" --password-stdin`, {
interactive: true,
});
await executeAsync(
`echo "${DOCKERHUB_PASS}" | docker login -u "${DOCKERHUB_USER}" --password-stdin`,
ExecOptionsPresets.INHERIT_OUTPUT_NO_SPINNER
);
logTask('docker:Dockerfile:push');
// tagging for versioning
await executeAsync(`docker tag ${imageName}:${appVersion} ${imageTag}:${appVersion}`);
Expand Down
27 changes: 16 additions & 11 deletions packages/sdk-android/src/deviceManager.ts
Expand Up @@ -26,6 +26,8 @@ import {
waitForExecCLI,
inquirerPrompt,
RnvPlatform,
executeAsync,
ExecOptionsPresets,
} from '@rnv/core';
import { CLI_ANDROID_EMULATOR, CLI_ANDROID_ADB, CLI_ANDROID_AVDMANAGER, CLI_ANDROID_SDKMANAGER } from './constants';

Expand Down Expand Up @@ -60,6 +62,7 @@ export const launchAndroidSimulator = async (
`target:${typeof target === 'object' ? target?.name : target} independentThread:${!!isIndependentThread}`
);
let newTarget: { name: string } | string;

if (target === true) {
const {
program: { device },
Expand All @@ -81,11 +84,13 @@ export const launchAndroidSimulator = async (

if (newTarget) {
const actualTarget = typeof newTarget === 'string' ? newTarget : newTarget.name;

if (isIndependentThread) {
execCLI(c, CLI_ANDROID_EMULATOR, `-avd "${actualTarget}"`, {
detached: isIndependentThread,
silent: true,
}).catch((err) => {
executeAsync(
c,
`${c.cli[CLI_ANDROID_EMULATOR]} -avd ${actualTarget}`,
ExecOptionsPresets.FIRE_AND_FORGET
).catch((err) => {
if (err.includes && err.includes('WHPX')) {
logWarning(err);
return logError(
Expand All @@ -97,10 +102,12 @@ export const launchAndroidSimulator = async (
});
return Promise.resolve();
}
return execCLI(c, CLI_ANDROID_EMULATOR, `-avd "${actualTarget}"`, {
detached: isIndependentThread,
silent: true,
});

return executeAsync(
c,
`${c.cli[CLI_ANDROID_EMULATOR]} -avd ${actualTarget}`,
ExecOptionsPresets.SPINNER_FULL_ERROR_SUMMARY
);
}
return Promise.reject('No simulator -t target name specified!');
};
Expand Down Expand Up @@ -611,9 +618,7 @@ const _createEmulator = (c: RnvContext, apiVersion: string, emuPlatform: string,
c,
CLI_ANDROID_AVDMANAGER,
`create avd -n ${emuName} -k "system-images;android-${apiVersion};${emuPlatform};x86"`,
{
interactive: true,
}
ExecOptionsPresets.INHERIT_OUTPUT_NO_SPINNER
)
)
.catch((e) => logError(e, true));
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk-react-native/src/androidRunner.ts
Expand Up @@ -14,6 +14,7 @@ import {
DEFAULTS,
RnvPlatform,
CoreEnvVars,
ExecOptionsPresets,
} from '@rnv/core';
import { EnvVars } from './env';

Expand Down Expand Up @@ -112,8 +113,7 @@ export const runReactNativeAndroid = async (
},
cwd: appFolder,
//This is required to make rn cli logs visible in rnv executed terminal
interactive: true,
stdio: 'inherit',
...ExecOptionsPresets.INHERIT_OUTPUT_NO_SPINNER,
});
};

Expand Down
5 changes: 2 additions & 3 deletions packages/sdk-webos/src/deviceManager.ts
Expand Up @@ -18,6 +18,7 @@ import {
RnvContext,
waitForExecCLI,
inquirerPrompt,
ExecOptionsPresets,
} from '@rnv/core';
import { WebosDevice } from './types';
import {
Expand Down Expand Up @@ -196,9 +197,7 @@ export const runWebosSimOrDevice = async (c: RnvContext) => {
logInfo(
'Please follow the instructions from http://webostv.developer.lge.com/develop/app-test/#installDevModeApp on how to setup the TV and the connection with the PC. Then follow the onscreen prompts\n'
);
await execCLI(c, CLI_WEBOS_ARES_SETUP_DEVICE, '', {
interactive: true,
});
await execCLI(c, CLI_WEBOS_ARES_SETUP_DEVICE, '', ExecOptionsPresets.INHERIT_OUTPUT_NO_SPINNER);

const newDeviceResponse = await execCLI(c, CLI_WEBOS_ARES_DEVICE_INFO, '-D');
const dev = await parseDevices(c, newDeviceResponse);
Expand Down