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(tvOS): Replace ios-deploy with xcrun commands in @react-native-community/cli-platfom-ios #1759

Merged
merged 7 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
"{\n isAvailable: device.available,": "{\n modelName:device.modelName, // <= PATCHED BY RENATIVE\n isAvailable: device.available,"
},
"build/commands/runIOS/index.js": {
"_cliTools().logger.error(`Could not find a device named: \"${_chalk().default.bold(String(deviceName))}\". ${printFoundDevices(devices)}`);": "_cliTools().logger.error(`Could not find a device: \"${_chalk().default.bold(String(deviceName))}\". ${printFoundDevices(devices)}`);\n throw 'Could not find device'; // <= PATCHED BY RENATIVE"
"_cliTools().logger.error(`Could not find a device named: \"${_chalk().default.bold(String(deviceName))}\". ${printFoundDevices(devices)}`);": "_cliTools().logger.error(`Could not find a device: \"${_chalk().default.bold(String(deviceName))}\". ${printFoundDevices(devices)}`);\n throw 'Could not find device'; // <= PATCHED BY RENATIVE",
"const isIOSDeployInstalled = _child_process().default.spawnSync('ios-deploy', ['--version'], {\n encoding: 'utf8'\n });\n if (isIOSDeployInstalled.error) {\n throw new (_cliTools().CLIError)(`Failed to install the app on the device because we couldn't execute the \"ios-deploy\" command. Please install it by running \"${_chalk().default.bold('brew install ios-deploy')}\" and try again.`); }": "// <= PATCHED BY RENATIVE, remove ios-deploy check",
"const iosDeployInstallArgs = ['--bundle', appPath, '--id', selectedDevice.udid, '--justlaunch'];": " if(!selectedDevice.modelName.includes('Apple TV')) {\n const iosDeployInstallArgs = ['--bundle', appPath, '--id', selectedDevice.udid, '--justlaunch'];",
"if (iosDeployOutput.error) {\n throw new (_cliTools().CLIError)(`Failed to install the app on the device. We've encountered an error in \"ios-deploy\" command: ${iosDeployOutput.error.message}`);\n }": "if (iosDeployOutput.error) {\n throw new (_cliTools().CLIError)(`Failed to install the app on the device. We've encountered an error in \"ios-deploy\" command: ${iosDeployOutput.error.message}`);\n }} else {\n _cliTools().logger.info(`Installing your app on ${selectedDevice.name}`);\n const iosInstallArgs = ['devicectl', 'device', 'install', 'app', '--device', selectedDevice.udid, appPath];\n _cliTools().logger.info(`xcrun ${iosInstallArgs.join(' ')}`);\n const iosInstallOutput = _child_process().default.spawnSync('xcrun', iosInstallArgs, {\n stdio: 'pipe',\n encoding: 'utf8',\n });\n const res = JSON.stringify(iosInstallOutput);\n const installationUrl = res.substring(\n res.indexOf('file:') || 0,\n (res.indexOf('.app/') || 0) + '.app/'.length\n );\n _cliTools().logger.info(`Launching your app on ${selectedDevice.name}`);\n const iosLaunchArgs = ['devicectl', 'device', 'process', 'launch', '--device', selectedDevice.udid, installationUrl];\n _cliTools().logger.info(`xcrun ${iosLaunchArgs.join(' ')}`);\n _child_process().default.spawnSync('xcrun', iosLaunchArgs, {\n stdio: 'inherit'\n });\n if (iosInstallOutput.stderr) {\n throw new (_cliTools().CLIError)(`Failed to install the app on the device. We've encountered an error: ${iosInstallOutput.stderr}`);\n }\n }"
}
}
}

44 changes: 2 additions & 42 deletions packages/sdk-apple/src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import {
import { registerDevice } from './fastlane';
import { Context, getContext } from './getContext';
import { parsePrivacyManifest } from './privacyManifestParser';
import { getAppId } from '@rnv/sdk-utils';

export const packageBundleForXcode = () => {
return packageReactNativeIOS();
Expand Down Expand Up @@ -233,48 +232,10 @@ export const runXcodeProject = async (runDeviceArguments?: string) => {
const bundleAssets = getConfigProp('bundleAssets') === true;

if (runDeviceArguments) {
// await launchAppleSimulator(c, c.runtime.target); @TODO - do we still need this? RN CLI does it as well
//const allowProvisioningUpdates = getConfigProp('allowProvisioningUpdates', true);
//if (allowProvisioningUpdates) p = `${p} --allowProvisioningUpdates`;
if (bundleAssets) {
await packageReactNativeIOS(bundleIsDev);
}
if (c.platform === 'tvos' && !runDeviceArguments.includes('--simulator')) {
try {
await executeAsync(`ios-deploy -c`);
} catch (error) {
if (typeof error === 'string' && error.includes('Command failed with exit code 253')) {
logError(
`Ios-deploy couldn't find a connected device. For a more reliable connection, use a USB cable instead of wireless.`
);
const { confirm } = await inquirerPrompt({
type: 'confirm',
name: 'confirm',
message: 'Would you like to use an Xcode script to build and launch the app?',
});
if (confirm) {
try {
await buildXcodeProject();
} catch (e) {
await _handleMissingTeam(c, e);
}
const udid = runDeviceArguments.split(' ')[1];

await executeAsync(
`xcrun devicectl device install app -d ${udid} ${path.join(
appPath,
`build/RNVApp/Build/Products/${runScheme}-appletvos/RNVApp-tvOS.app`
)}`
);

return executeAsync(
`xcrun devicectl device process launch --device ${udid} --activate ${getAppId()?.toLowerCase()}`
);
}
return;
}
}
}

return _checkLockAndExec(c, appPath, schemeTarget, runScheme, runDeviceArguments);
}

Expand All @@ -293,7 +254,6 @@ export const runXcodeProject = async (runDeviceArguments?: string) => {
`open ${path.join(appPath, `build/RNVApp/Build/Products/${runScheme}-maccatalyst/RNVApp.app`)}`
);
}
// return Promise.reject('Missing options for react-native command!');
};

const _checkLockAndExec = async (
Expand Down Expand Up @@ -327,7 +287,7 @@ const _checkLockAndExec = async (
logWarning(
`${c.platform} DEVICE: ${chalk().bold.white(c.runtime.target)} with UDID: ${chalk().bold.white(
c.runtime.targetUDID
)} is not included in your provisionong profile in TEAM: ${chalk().bold.white(
)} is not included in your provisioning profile in TEAM: ${chalk().bold.white(
getConfigProp('teamID')
)}`
);
Expand Down
15 changes: 15 additions & 0 deletions packages/sdk-react-native/src/iosRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ import {
inquirerPrompt,
RnvEnvContext,
isOfflineMode,
logWarning,
} from '@rnv/core';
import { EnvVars } from './env';
import shellQuote from 'shell-quote';
import path from 'path';
import crypto from 'crypto';
import { ObjectEncodingOptions } from 'fs';
import child_process, { ExecFileOptions } from 'child_process';

export const packageReactNativeIOS = (isDev = false) => {
const c = getContext();
Expand Down Expand Up @@ -93,6 +96,18 @@ export const runReactNativeIOS = async (
};

try {
// Check if it's an older XCode and show a warning as xcrun commands used
// to install and launch were introduced in xcode 15
const opts: ObjectEncodingOptions & ExecFileOptions = { encoding: 'utf8' };
const child = child_process.spawnSync('xcodebuild', ['-version'], opts);
const xcodeVersion =
JSON.stringify(child.stdout).substring(
JSON.stringify(child.stdout).indexOf('Xcode ') + 6,
JSON.stringify(child.stdout).indexOf('Build') - 2
) || '0';
if (Number(xcodeVersion) < 15)
logWarning('Installing application and launching it with an Xcode older than 15 may not work');

// Inherit full logs
// return executeAsync(c, cmd, { stdio: 'inherit', silent: true });
return executeAsync(cmd, {
Expand Down
Loading