Skip to content

Commit

Permalink
[eas-cli] Use expo-updates runtime version CLI to generate runtime ve…
Browse files Browse the repository at this point in the history
…rsions
  • Loading branch information
wschurman committed Feb 27, 2024
1 parent 33c965b commit edaa89f
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 48 deletions.
6 changes: 2 additions & 4 deletions packages/eas-cli/src/build/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Updates } from '@expo/config-plugins';
import { Metadata, Platform, sanitizeMetadata } from '@expo/eas-build-job';
import { IosEnterpriseProvisioning } from '@expo/eas-json';
import fs from 'fs-extra';
Expand All @@ -15,6 +14,7 @@ import {
isClassicUpdatesSupportedAsync,
isExpoUpdatesInstalled,
} from '../project/projectUtils';
import { resolveRuntimeVersionAsync } from '../project/resolveRuntimeVersionAsync';
import {
readChannelSafelyAsync as readAndroidChannelSafelyAsync,
readReleaseChannelSafelyAsync as readAndroidReleaseChannelSafelyAsync,
Expand All @@ -37,9 +37,7 @@ export async function collectMetadataAsync<T extends Platform>(
workflow: ctx.workflow,
credentialsSource: ctx.buildProfile.credentialsSource,
sdkVersion: ctx.exp.sdkVersion,
runtimeVersion:
(await Updates.getRuntimeVersionNullableAsync(ctx.projectDir, ctx.exp, ctx.platform)) ??
undefined,
runtimeVersion: (await resolveRuntimeVersionAsync(ctx)) ?? undefined,
reactNativeVersion: await getReactNativeVersionAsync(ctx.projectDir),
...channelOrReleaseChannel,
distribution,
Expand Down
47 changes: 23 additions & 24 deletions packages/eas-cli/src/project/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import {
shouldUseVersionedExpoCLI,
shouldUseVersionedExpoCLIWithExplicitPlatforms,
} from '../utils/expoCli';
import { expoUpdatesCommandAsync } from '../utils/expoUpdatesCli';
import {
ExpoUpdatesCLIInvalidCommandError,
ExpoUpdatesCLIModuleNotFoundError,
expoUpdatesCommandAsync,
} from '../utils/expoUpdatesCli';
import chunk from '../utils/expodash/chunk';
import { truthy } from '../utils/expodash/filter';
import uniqBy from '../utils/expodash/uniqBy';
Expand Down Expand Up @@ -717,31 +721,26 @@ async function getRuntimeVersionForPlatformAsync({
return 'UNVERSIONED';
}

const runtimeVersion = exp[platform]?.runtimeVersion ?? exp.runtimeVersion;
if (typeof runtimeVersion === 'object') {
const policy = runtimeVersion.policy;

if (policy === 'fingerprintExperimental') {
// log to inform the user that the fingerprint has been calculated
Log.warn(
`Calculating native fingerprint for platform ${platform} using current state of the "${platform}" directory. ` +
`If the fingerprint differs from the build's fingerint, ensure the state of your project is consistent ` +
`(repository is clean, ios and android native directories are in the same state as the build if applicable).`
);

const fingerprintRawString = await expoUpdatesCommandAsync(projectDir, [
'fingerprint:generate',
'--platform',
platform,
]);
const fingerprintObject = JSON.parse(fingerprintRawString);
const hash = nullthrows(
fingerprintObject.hash,
'invalid response from expo-update CLI for fingerprint generation'
);
return hash;
try {
const runtimeString = await expoUpdatesCommandAsync(projectDir, [
'runtimeversion:resolve',
'--platform',
platform,
]);
return nullthrows(JSON.parse(runtimeString).runtimeVersion);
} catch (e: any) {
// if it's a known set of errors thrown by the CLI it means that we need to default back to the
// previous behavior, otherwise we throw the error since something is wrong
if (
!(e instanceof ExpoUpdatesCLIModuleNotFoundError) &&
!(e instanceof ExpoUpdatesCLIInvalidCommandError)
) {
throw e;
}
}

const runtimeVersion = exp[platform]?.runtimeVersion ?? exp.runtimeVersion;
if (typeof runtimeVersion === 'object') {
const workflow = await resolveWorkflowAsync(
projectDir,
platform as EASBuildJobPlatform,
Expand Down
39 changes: 39 additions & 0 deletions packages/eas-cli/src/project/resolveRuntimeVersionAsync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ExpoConfig } from '@expo/config';
import { Updates } from '@expo/config-plugins';

import {
ExpoUpdatesCLIInvalidCommandError,
ExpoUpdatesCLIModuleNotFoundError,
expoUpdatesCommandAsync,
} from '../utils/expoUpdatesCli';

export async function resolveRuntimeVersionAsync({
exp,
platform,
projectDir,
}: {
exp: ExpoConfig;
platform: 'ios' | 'android';
projectDir: string;
}): Promise<string | null> {
try {
const runtimeJSONString = await expoUpdatesCommandAsync(projectDir, [
'runtimeversion:resolve',
'--platform',
platform,
]);
const runtimeVersion = JSON.parse(runtimeJSONString).runtimeVersion;
return runtimeVersion ?? null;
} catch (e: any) {
// if expo-updates is not installed, there's no need for a runtime version in the build
if (e instanceof ExpoUpdatesCLIModuleNotFoundError) {
return null;
} else if (e instanceof ExpoUpdatesCLIInvalidCommandError) {
// fall back to the previous behavior (using the @expo/config-plugins eas-cli dependency rather
// than the versioned @expo/config-plugins dependency in the project)
return await Updates.getRuntimeVersionNullableAsync(projectDir, exp, platform);
}

throw e;
}
}
4 changes: 2 additions & 2 deletions packages/eas-cli/src/rollout/actions/CreateRollout.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Updates } from '@expo/config-plugins';
import assert from 'assert';

import { SelectRuntime } from './SelectRuntime';
Expand All @@ -24,6 +23,7 @@ import {
} from '../../graphql/queries/ChannelQuery';
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
import Log from '../../log';
import { resolveRuntimeVersionAsync } from '../../project/resolveRuntimeVersionAsync';
import { confirmAsync, promptAsync } from '../../prompts';
import { truthy } from '../../utils/expodash/filter';
import {
Expand Down Expand Up @@ -275,7 +275,7 @@ export class CreateRollout implements EASUpdateAction<UpdateChannelBasicInfoFrag
const runtimes = (
await Promise.all(
platforms.map(platform =>
Updates.getRuntimeVersionAsync(ctx.app.projectDir, ctx.app.exp, platform)
resolveRuntimeVersionAsync({ projectDir: ctx.app.projectDir, exp: ctx.app.exp, platform })
)
)
).filter(truthy);
Expand Down
34 changes: 16 additions & 18 deletions packages/eas-cli/src/utils/expoUpdatesCli.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import spawnAsync from '@expo/spawn-async';
import chalk from 'chalk';
import resolveFrom, { silent as silentResolveFrom } from 'resolve-from';

import Log, { link } from '../log';
import { link } from '../log';

export class ExpoUpdatesCLIModuleNotFoundError extends Error {}
export class ExpoUpdatesCLIInvalidCommandError extends Error {}

export async function expoUpdatesCommandAsync(projectDir: string, args: string[]): Promise<string> {
let expoUpdatesCli;
Expand All @@ -12,7 +14,7 @@ export async function expoUpdatesCommandAsync(projectDir: string, args: string[]
resolveFrom(projectDir, 'expo-updates/bin/cli.js');
} catch (e: any) {
if (e.code === 'MODULE_NOT_FOUND') {
throw new Error(
throw new ExpoUpdatesCLIModuleNotFoundError(
`The \`expo-updates\` package was not found. Follow the installation directions at ${link(
'https://docs.expo.dev/bare/installing-expo-modules/'
)}`
Expand All @@ -21,20 +23,16 @@ export async function expoUpdatesCommandAsync(projectDir: string, args: string[]
throw e;
}

const spawnPromise = spawnAsync(expoUpdatesCli, args, {
stdio: ['inherit', 'pipe', 'pipe'], // inherit stdin so user can install a missing expo-cli from inside this command
});
const {
child: { stderr },
} = spawnPromise;
if (!stderr) {
throw new Error('Failed to spawn expo-updates cli');
}
stderr.on('data', data => {
for (const line of data.toString().trim().split('\n')) {
Log.warn(`${chalk.gray('[expo-cli]')} ${line}`);
try {
return (await spawnAsync(expoUpdatesCli, args)).stdout;
} catch (e: any) {
if (e.stderr) {
if ((e.stderr as string).includes('Invalid command')) {
throw new ExpoUpdatesCLIInvalidCommandError(
`The command specified by ${args} was not valid in the \`expo-updates\` CLI.`
);
}
}
});
const result = await spawnPromise;
return result.stdout;
throw e;
}
}

0 comments on commit edaa89f

Please sign in to comment.