From bdb7cb04ff5cda2a7061084501151cfe5d16d11b Mon Sep 17 00:00:00 2001 From: Will Schurman Date: Sat, 24 Feb 2024 10:39:03 -0700 Subject: [PATCH] [eas-cli] Use expo-updates runtime version CLI to generate runtime versions --- packages/eas-cli/src/build/metadata.ts | 6 ++-- packages/eas-cli/src/project/publish.ts | 32 +++++------------- .../src/project/resolveRuntimeVersionAsync.ts | 33 +++++++++++++++++++ .../src/rollout/actions/CreateRollout.ts | 4 +-- packages/eas-cli/src/utils/expoUpdatesCli.ts | 9 +++-- 5 files changed, 52 insertions(+), 32 deletions(-) create mode 100644 packages/eas-cli/src/project/resolveRuntimeVersionAsync.ts diff --git a/packages/eas-cli/src/build/metadata.ts b/packages/eas-cli/src/build/metadata.ts index 4393ce2d1c..34497ec1f4 100644 --- a/packages/eas-cli/src/build/metadata.ts +++ b/packages/eas-cli/src/build/metadata.ts @@ -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'; @@ -15,6 +14,7 @@ import { isClassicUpdatesSupportedAsync, isExpoUpdatesInstalled, } from '../project/projectUtils'; +import { resolveRuntimeVersionAsync } from '../project/resolveRuntimeVersionAsync'; import { readChannelSafelyAsync as readAndroidChannelSafelyAsync, readReleaseChannelSafelyAsync as readAndroidReleaseChannelSafelyAsync, @@ -37,9 +37,7 @@ export async function collectMetadataAsync( 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, diff --git a/packages/eas-cli/src/project/publish.ts b/packages/eas-cli/src/project/publish.ts index 4fee6853a8..b29ad86db1 100644 --- a/packages/eas-cli/src/project/publish.ts +++ b/packages/eas-cli/src/project/publish.ts @@ -717,31 +717,17 @@ async function getRuntimeVersionForPlatformAsync({ return 'UNVERSIONED'; } + try { + const runtimeString = await expoUpdatesCommandAsync(projectDir, [ + 'runtimeversion:resolve', + '--platform', + platform, + ]); + return nullthrows(runtimeString); + } catch {} + 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; - } - const workflow = await resolveWorkflowAsync( projectDir, platform as EASBuildJobPlatform, diff --git a/packages/eas-cli/src/project/resolveRuntimeVersionAsync.ts b/packages/eas-cli/src/project/resolveRuntimeVersionAsync.ts new file mode 100644 index 0000000000..6f76fef2a8 --- /dev/null +++ b/packages/eas-cli/src/project/resolveRuntimeVersionAsync.ts @@ -0,0 +1,33 @@ +import { ExpoConfig } from '@expo/config'; +import { Updates } from '@expo/config-plugins'; + +import { ModuleNotFoundError, expoUpdatesCommandAsync } from '../utils/expoUpdatesCli'; + +export async function resolveRuntimeVersionAsync({ + exp, + platform, + projectDir, +}: { + exp: ExpoConfig; + platform: 'ios' | 'android'; + projectDir: string; +}): Promise { + 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 ModuleNotFoundError) { + return null; + } + + // 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); + } +} diff --git a/packages/eas-cli/src/rollout/actions/CreateRollout.ts b/packages/eas-cli/src/rollout/actions/CreateRollout.ts index c104a988ef..85f56ba959 100644 --- a/packages/eas-cli/src/rollout/actions/CreateRollout.ts +++ b/packages/eas-cli/src/rollout/actions/CreateRollout.ts @@ -1,4 +1,3 @@ -import { Updates } from '@expo/config-plugins'; import assert from 'assert'; import { SelectRuntime } from './SelectRuntime'; @@ -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 { @@ -275,7 +275,7 @@ export class CreateRollout implements EASUpdateAction - Updates.getRuntimeVersionAsync(ctx.app.projectDir, ctx.app.exp, platform) + resolveRuntimeVersionAsync({ projectDir: ctx.app.projectDir, exp: ctx.app.exp, platform }) ) ) ).filter(truthy); diff --git a/packages/eas-cli/src/utils/expoUpdatesCli.ts b/packages/eas-cli/src/utils/expoUpdatesCli.ts index 0119d31df2..674c395571 100644 --- a/packages/eas-cli/src/utils/expoUpdatesCli.ts +++ b/packages/eas-cli/src/utils/expoUpdatesCli.ts @@ -4,6 +4,8 @@ import resolveFrom, { silent as silentResolveFrom } from 'resolve-from'; import Log, { link } from '../log'; +export class ModuleNotFoundError extends Error {} + export async function expoUpdatesCommandAsync(projectDir: string, args: string[]): Promise { let expoUpdatesCli; try { @@ -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 ModuleNotFoundError( `The \`expo-updates\` package was not found. Follow the installation directions at ${link( 'https://docs.expo.dev/bare/installing-expo-modules/' )}` @@ -22,7 +24,7 @@ export async function expoUpdatesCommandAsync(projectDir: string, args: string[] } const spawnPromise = spawnAsync(expoUpdatesCli, args, { - stdio: ['inherit', 'pipe', 'pipe'], // inherit stdin so user can install a missing expo-cli from inside this command + stdio: ['inherit', 'pipe', 'pipe'], }); const { child: { stderr }, @@ -30,9 +32,10 @@ export async function expoUpdatesCommandAsync(projectDir: string, args: string[] 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}`); + Log.debug(`${chalk.gray('[expo-updates-cli]')} ${line}`); } }); const result = await spawnPromise;