Skip to content

Commit 50ca4cb

Browse files
authored
[eas-cli] Restore iOS entitlements introspection fallback (#3753)
## Summary - wrap managed iOS `expo config --json --type introspect` entitlement resolution in a local Expo CLI try/catch - fall back to bundled `getPrebuildConfigAsync` + `compileModsAsync`, matching the previous behavior - include stderr/stdout in the thrown error when both the local CLI and fallback fail - check `isExpoInstalled` before spawning the local Expo CLI, consistent with the regular config reader ## Why After `18.13.1`, managed iOS builds fail hard if the local Expo CLI introspection command exits non-zero. Previously this path could still resolve entitlements through the bundled config fallback. Restoring that fallback limits the regression while preserving the local CLI path when it is available. ## Validation CI should pass.
1 parent 2dbb437 commit 50ca4cb

3 files changed

Lines changed: 84 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This is the log of notable changes to EAS CLI and related packages.
1111
### 🐛 Bug fixes
1212

1313
- [eas-cli] Disable dotenv loading when resolving managed iOS entitlements. ([#3752](https://github.com/expo/eas-cli/pull/3752) by [@sjchmiela](https://github.com/sjchmiela))
14+
- [eas-cli] Restore the bundled config fallback for managed iOS entitlements introspection. ([#3753](https://github.com/expo/eas-cli/pull/3753) by [@sjchmiela](https://github.com/sjchmiela))
1415

1516
### 🧹 Chores
1617

packages/eas-cli/src/project/ios/entitlements.ts

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import { ExportedConfig, IOSConfig } from '@expo/config-plugins';
1+
import { ExportedConfig, IOSConfig, compileModsAsync } from '@expo/config-plugins';
22
import { JSONObject } from '@expo/json-file';
3+
import { getPrebuildConfigAsync } from '@expo/prebuild-config';
34

5+
import Log from '../../log';
46
import { spawnExpoCommand } from '../../utils/expoCli';
57
import { readPlistAsync } from '../../utils/plist';
8+
import { Client } from '../../vcs/vcs';
9+
import { isExpoInstalled } from '../projectUtils';
10+
import { hasIgnoredIosProjectAsync } from '../workflow';
611

712
interface Target {
813
buildConfiguration?: string;
@@ -11,20 +16,83 @@ interface Target {
1116

1217
export async function getManagedApplicationTargetEntitlementsAsync(
1318
projectDir: string,
14-
env: Record<string, string>
19+
env: Record<string, string>,
20+
vcsClient: Client
1521
): Promise<JSONObject> {
16-
const { stdout } = await spawnExpoCommand(
17-
projectDir,
18-
['config', '--json', '--type', 'introspect'],
19-
{
20-
env: {
21-
...env,
22-
EXPO_NO_DOTENV: '1',
23-
},
22+
let expoConfigError: Error | undefined;
23+
if (isExpoInstalled(projectDir)) {
24+
try {
25+
const { stdout } = await spawnExpoCommand(
26+
projectDir,
27+
['config', '--json', '--type', 'introspect'],
28+
{
29+
env: {
30+
...env,
31+
EXPO_NO_DOTENV: '1',
32+
},
33+
}
34+
);
35+
const expWithMods: ExportedConfig = JSON.parse(stdout);
36+
return expWithMods.ios?.entitlements ?? {};
37+
} catch (error: any) {
38+
expoConfigError = error;
39+
Log.warn(
40+
`Failed to read the app config from the project using the local Expo CLI: ${formatError(error)}`
41+
);
42+
Log.warn('Falling back to the version of "@expo/config" shipped with the EAS CLI.');
2443
}
25-
);
26-
const expWithMods: ExportedConfig = JSON.parse(stdout);
27-
return expWithMods.ios?.entitlements ?? {};
44+
}
45+
46+
try {
47+
return await resolveManagedApplicationTargetEntitlementsWithBundledConfigAsync(
48+
projectDir,
49+
env,
50+
vcsClient
51+
);
52+
} catch (fallbackError: any) {
53+
if (expoConfigError) {
54+
throw new Error(
55+
`Failed to resolve iOS entitlements from Expo config. The local Expo CLI failed with: ${formatError(
56+
expoConfigError
57+
)}. The bundled config fallback also failed with: ${formatError(fallbackError)}`,
58+
{ cause: fallbackError }
59+
);
60+
}
61+
throw new Error(
62+
`Failed to resolve iOS entitlements from Expo config using the bundled config fallback: ${formatError(
63+
fallbackError
64+
)}`,
65+
{ cause: fallbackError }
66+
);
67+
}
68+
}
69+
70+
async function resolveManagedApplicationTargetEntitlementsWithBundledConfigAsync(
71+
projectDir: string,
72+
env: Record<string, string>,
73+
vcsClient: Client
74+
): Promise<JSONObject> {
75+
const originalProcessEnv = process.env;
76+
try {
77+
process.env = {
78+
...process.env,
79+
...env,
80+
};
81+
const { exp } = await getPrebuildConfigAsync(projectDir, { platforms: ['ios'] });
82+
const expWithMods = await compileModsAsync(exp, {
83+
projectRoot: projectDir,
84+
platforms: ['ios'],
85+
introspect: true,
86+
ignoreExistingNativeFiles: await hasIgnoredIosProjectAsync(projectDir, vcsClient),
87+
});
88+
return expWithMods.ios?.entitlements ?? {};
89+
} finally {
90+
process.env = originalProcessEnv;
91+
}
92+
}
93+
94+
function formatError(error: Error & { stderr?: string; stdout?: string }): string {
95+
return error.stderr?.trim() || error.stdout?.trim() || error.message;
2896
}
2997

3098
export async function getNativeTargetEntitlementsAsync(

packages/eas-cli/src/project/ios/target.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ export async function resolveManagedProjectTargetsAsync({
6060
);
6161
const applicationTargetEntitlements = await getManagedApplicationTargetEntitlementsAsync(
6262
projectDir,
63-
env ?? {}
63+
env ?? {},
64+
vcsClient
6465
);
6566
const appExtensions: UserDefinedTarget[] =
6667
exp.extra?.eas?.build?.experimental?.ios?.appExtensions ?? [];

0 commit comments

Comments
 (0)