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: log-ios command #1890

Merged
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
5 changes: 4 additions & 1 deletion __e2e__/__snapshots__/config.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ exports[`shows up current config without unnecessary output 1`] = `
"commands": [
{
"name": "log-ios",
"description": "starts iOS device syslog tail"
"description": "starts iOS device syslog tail",
"options": [
"<<REPLACED>>"
]
},
{
"name": "run-ios",
Expand Down
6 changes: 6 additions & 0 deletions packages/cli-platform-ios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ react-native log-ios

Starts iOS device syslog tail.

#### Options

#### `--interactive`

Explicitly select simulator to tail logs from. By default it will tail logs from the first booted and available simulator.

## License

Everything inside this repository is [MIT licensed](./LICENSE).
74 changes: 50 additions & 24 deletions packages/cli-platform-ios/src/commands/logIOS/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,63 @@
*
*/

import {execFileSync, spawnSync} from 'child_process';
import {spawnSync} from 'child_process';
import os from 'os';
import path from 'path';
import {logger} from '@react-native-community/cli-tools';
import {Device} from '../../types';

function findAvailableDevice(devices: {[index: string]: Array<Device>}) {
for (const key of Object.keys(devices)) {
for (const device of devices[key]) {
if (device.availability === '(available)' && device.state === 'Booted') {
return device;
}
}
}
return null;
}
import listIOSDevices from '../../tools/listIOSDevices';
import getSimulators from '../../tools/getSimulators';
import {Config} from '@react-native-community/cli-types';
import prompts from 'prompts';

/**
* Starts iOS device syslog tail
*/
async function logIOS() {
const rawDevices = execFileSync(
'xcrun',
['simctl', 'list', 'devices', '--json'],
{encoding: 'utf8'},

type Args = {
interactive: boolean;
};

async function logIOS(_argv: Array<string>, _ctx: Config, args: Args) {
// Here we're using two command because first command `xcrun simctl list --json devices` outputs `state` but doesn't return `available`. But second command `xcrun xcdevice list` outputs `available` but doesn't output `state`. So we need to connect outputs of both commands.
const simulators = getSimulators();
const bootedSimulators = Object.keys(simulators.devices)
.map((key) => simulators.devices[key])
.reduce((acc, val) => acc.concat(val), [])
.filter(({state}) => state === 'Booted');

const devices = await listIOSDevices();
const availableSimulators = devices.filter(
({type, isAvailable}) => type === 'simulator' && isAvailable,
);

const {devices} = JSON.parse(rawDevices) as {
devices: {[index: string]: Array<Device>};
};
const bootedAndAvailableSimulators = bootedSimulators.map((booted) => {
const available = availableSimulators.find(
({udid}) => udid === booted.udid,
);
return {...available, ...booted};
});

const device = findAvailableDevice(devices);
if (device === null) {
if (bootedAndAvailableSimulators.length === 0) {
logger.error('No active iOS device found');
return;
}

tailDeviceLogs(device.udid);
if (args.interactive && bootedAndAvailableSimulators.length > 1) {
const {udid} = await prompts({
type: 'select',
name: 'udid',
message: 'Select iOS simulators to tail logs from',
choices: bootedAndAvailableSimulators.map((simulator) => ({
title: simulator.name,
value: simulator.udid,
})),
});

tailDeviceLogs(udid);
} else {
tailDeviceLogs(bootedAndAvailableSimulators[0].udid);
}
}

function tailDeviceLogs(udid: string) {
Expand All @@ -69,4 +88,11 @@ export default {
name: 'log-ios',
description: 'starts iOS device syslog tail',
func: logIOS,
options: [
{
name: '--interactive',
description:
'Explicitly select simulator to tail logs from. By default it will tail logs from the first booted and available simulator.',
},
],
};
20 changes: 1 addition & 19 deletions packages/cli-platform-ios/src/commands/runIOS/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {getProjectInfo} from '../../tools/getProjectInfo';
import {getConfigurationScheme} from '../../tools/getConfigurationScheme';
import {selectFromInteractiveMode} from '../../tools/selectFromInteractiveMode';
import {promptForDeviceSelection} from '../../tools/prompts';
import getSimulators from '../../tools/getSimulators';

export interface FlagsT extends BuildFlags {
simulator?: string;
Expand Down Expand Up @@ -203,25 +204,6 @@ async function runIOS(_: Array<string>, ctx: Config, args: FlagsT) {
}
}

const getSimulators = () => {
let simulators: {devices: {[index: string]: Array<Device>}};

try {
simulators = JSON.parse(
child_process.execFileSync(
'xcrun',
['simctl', 'list', '--json', 'devices'],
{encoding: 'utf8'},
),
);
} catch (error) {
throw new CLIError(
'Could not get the simulator list from Xcode. Please open Xcode and try running project directly from there to resolve the remaining issues.',
);
}
return simulators;
};

async function runOnBootedDevicesSimulators(
scheme: string,
xcodeProject: IOSProjectInfo,
Expand Down
24 changes: 24 additions & 0 deletions packages/cli-platform-ios/src/tools/getSimulators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {CLIError} from '@react-native-community/cli-tools';
import child_process from 'child_process';
import {Device} from '../types';

const getSimulators = () => {
let simulators: {devices: {[index: string]: Array<Device>}};

try {
simulators = JSON.parse(
child_process.execFileSync(
'xcrun',
['simctl', 'list', '--json', 'devices'],
{encoding: 'utf8'},
),
);
} catch (error) {
throw new CLIError(
'Could not get the simulator list from Xcode. Please open Xcode and try running project directly from there to resolve the remaining issues.',
);
}
return simulators;
};

export default getSimulators;