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: get scheme from xcodeProject name #2121

Merged
merged 7 commits into from
Oct 26, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,35 @@ import chalk from 'chalk';
import {IOSProjectInfo} from '@react-native-community/cli-types';
import {logger} from '@react-native-community/cli-tools';
import {selectFromInteractiveMode} from '../../tools/selectFromInteractiveMode';
import {getProjectInfo} from '../../tools/getProjectInfo';
import {getInfo} from '../../tools/getInfo';
import {checkIfConfigurationExists} from '../../tools/checkIfConfigurationExists';
import type {BuildFlags} from './buildOptions';
import {getBuildConfigurationFromXcScheme} from '../../tools/getBuildConfigurationFromXcScheme';
import path from 'path';

export async function getConfiguration(
xcodeProject: IOSProjectInfo,
sourceDir: string,
args: BuildFlags,
) {
const projectInfo = getProjectInfo();
const info = getInfo();

if (args.mode) {
checkIfConfigurationExists(projectInfo, args.mode);
checkIfConfigurationExists((info && info.configurations) ?? [], args.mode);
szymonrybczak marked this conversation as resolved.
Show resolved Hide resolved
}

let scheme = args.scheme || projectInfo.schemes[0];
let scheme =
args.scheme ||
path.basename(xcodeProject.name, path.extname(xcodeProject.name));
let mode =
args.mode ||
getBuildConfigurationFromXcScheme(scheme, 'Debug', sourceDir, projectInfo);
getBuildConfigurationFromXcScheme(scheme, 'Debug', sourceDir, info);

if (args.interactive) {
const selection = await selectFromInteractiveMode({
scheme,
mode,
projectInfo,
info,
});

if (selection.scheme) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import type {IosProjectInfo} from '../../types';
import {checkIfConfigurationExists} from '../checkIfConfigurationExists';

const CONFIGURATIONS = ['Debug', 'Release'];
const NON_EXISTING_CONFIG = 'Test';
const PROJECT_INFO = {
configurations: CONFIGURATIONS,
name: 'MyApp',
schemes: ['MyApp', 'Scheme'],
targets: ['MyApp', 'MyAppTests'],
};

describe('checkIfConfigurationExists', () => {
test('should throw an error if project info does not contain selected configuration', () => {
const checkConfig = () =>
checkIfConfigurationExists(PROJECT_INFO, NON_EXISTING_CONFIG);
checkIfConfigurationExists(CONFIGURATIONS, NON_EXISTING_CONFIG);

expect(checkConfig).toThrowError(
`Configuration "${NON_EXISTING_CONFIG}" does not exist in your project. Please use one of the existing configurations: ${CONFIGURATIONS.join(
Expand All @@ -23,14 +16,14 @@ describe('checkIfConfigurationExists', () => {
});

test('should not throw an error if project info contains selected configuration', () => {
const checkConfig = () => checkIfConfigurationExists(PROJECT_INFO, 'Debug');
const checkConfig = () =>
checkIfConfigurationExists(CONFIGURATIONS, 'Debug');

expect(checkConfig).not.toThrow();
});

test('should not throw an error if project could not be found', () => {
const checkConfig = () =>
checkIfConfigurationExists(undefined as IosProjectInfo, 'Debug');
const checkConfig = () => checkIfConfigurationExists([], 'Debug');

expect(checkConfig).not.toThrow();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import {CLIError, logger} from '@react-native-community/cli-tools';
import {IosProjectInfo} from '../types';

export function checkIfConfigurationExists(
project: IosProjectInfo,
configurations: string[],
mode: string,
) {
if (!project) {
if (configurations.length === 0) {
logger.warn(`Unable to check whether "${mode}" exists in your project`);
return;
}

if (!project.configurations.includes(mode)) {
if (!configurations.includes(mode)) {
throw new CLIError(
`Configuration "${mode}" does not exist in your project. Please use one of the existing configurations: ${project.configurations.join(
`Configuration "${mode}" does not exist in your project. Please use one of the existing configurations: ${configurations.join(
', ',
)}`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import chalk from 'chalk';
import {XMLParser} from 'fast-xml-parser';
import fs from 'fs';
import path from 'path';
import {IosProjectInfo} from '../types';
import {IosInfo} from '../types';

const xmlParser = new XMLParser({ignoreAttributes: false});

export function getBuildConfigurationFromXcScheme(
scheme: string,
configuration: string,
sourceDir: string,
projectInfo: IosProjectInfo,
projectInfo: IosInfo | undefined,
): string {
try {
const xcProject = fs
Expand All @@ -37,10 +37,15 @@ export function getBuildConfigurationFromXcScheme(
return Scheme.LaunchAction['@_buildConfiguration'];
}
} catch {
const availableSchemas =
projectInfo && projectInfo.schemes && projectInfo.schemes.length > 0
? `Available schemas are: ${projectInfo.schemes
.map((name) => chalk.bold(name))
.join(', ')}'`
: '';

throw new CLIError(
`Could not find scheme ${scheme}. Please make sure the schema you want to run exists. Available schemas are: ${projectInfo.schemes
.map((name) => chalk.bold(name))
.join(', ')}'`,
`Could not find scheme ${scheme}. Please make sure the schema you want to run exists. ${availableSchemas}`,
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import execa from 'execa';
import {IosProjectInfo} from '../types';
import {IosInfo} from '../types';

export function getProjectInfo(): IosProjectInfo {
export function getInfo(): IosInfo | undefined {
try {
const out = execa.sync('xcodebuild', ['-list', '-json']).stdout;
const {project} = JSON.parse(out);
return project;
const value = JSON.parse(
execa.sync('xcodebuild', ['-list', '-json']).stdout,
);

if ('project' in value) {
return value.project;
} else if ('workspace' in value) {
return value.workspace;
}

return undefined;
} catch (error) {
if (
(error as Error)?.message &&
Expand Down
10 changes: 5 additions & 5 deletions packages/cli-platform-ios/src/tools/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import chalk from 'chalk';
import prompts from 'prompts';
import {Device, IosProjectInfo} from '../types';
import {Device} from '../types';

export async function promptForSchemeSelection(
project: IosProjectInfo,
schemes: string[],
): Promise<string> {
const {scheme} = await prompts({
name: 'scheme',
type: 'select',
message: 'Select the scheme you want to use',
choices: project.schemes.map((value) => ({
choices: schemes.map((value) => ({
title: value,
value: value,
})),
Expand All @@ -19,13 +19,13 @@ export async function promptForSchemeSelection(
}

export async function promptForConfigurationSelection(
project: IosProjectInfo,
configurations: string[],
): Promise<string> {
const {configuration} = await prompts({
name: 'configuration',
type: 'select',
message: 'Select the configuration you want to use',
choices: project.configurations.map((value) => ({
choices: configurations.map((value) => ({
title: value,
value: value,
})),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {logger} from '@react-native-community/cli-tools';
import chalk from 'chalk';
import {IosProjectInfo} from '../types';
import {IosInfo} from '../types';
import {
promptForConfigurationSelection,
promptForSchemeSelection,
Expand All @@ -9,25 +9,25 @@ import {
interface Args {
scheme?: string;
mode?: string;
projectInfo: IosProjectInfo;
info: IosInfo | undefined;
}

export async function selectFromInteractiveMode({
scheme,
mode,
projectInfo,
info,
}: Args): Promise<{scheme?: string; mode?: string}> {
let newScheme = scheme;
let newMode = mode;

if (projectInfo.schemes.length > 1) {
newScheme = await promptForSchemeSelection(projectInfo);
if (info && info?.schemes && info.schemes.length > 1) {
newScheme = await promptForSchemeSelection(info.schemes);
szymonrybczak marked this conversation as resolved.
Show resolved Hide resolved
} else {
logger.info(`Automatically selected ${chalk.bold(scheme)} scheme.`);
}

if (projectInfo.configurations.length > 1) {
newMode = await promptForConfigurationSelection(projectInfo);
if (info && info?.configurations && info?.configurations?.length > 1) {
newMode = await promptForConfigurationSelection(info.configurations);
szymonrybczak marked this conversation as resolved.
Show resolved Hide resolved
} else {
logger.info(`Automatically selected ${chalk.bold(mode)} configuration.`);
}
Expand Down
8 changes: 4 additions & 4 deletions packages/cli-platform-ios/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export interface Device {
lastBootedAt?: string;
}

export interface IosProjectInfo {
configurations: string[];
export interface IosInfo {
name: string;
schemes: string[];
targets: string[];
schemes?: string[];
configurations?: string[];
targets?: string[];
}
Loading