Compare commits

...
9 Commits
Author SHA1 Message Date
Expo CI cd47185f29 v20.5.1 2026-07-01 16:34:31 +00:00
88c51c3ccc [eas-cli] Fix Free plan users being falsely warned they hit their build limit (#3927)
The "over" usage tier fired whenever the summed value of any overageMetrics
row was greater than zero, independent of the plan limit or whether a charge
was actually incurred. For Free plans that message collapsed into the
"you've reached your limit, upgrade to keep building" warning, so free users
well below their limit (e.g. 6 builds) were told they were blocked.

Free plans can never be in an "over" state (they are blocked at the limit
and never charged pay-as-you-go), and even paid plans now require a real
billable overage cost (totalCost > 0) before showing the overage warning.

Co-authored-by: Sarah Lane <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-01 09:38:27 -06:00
Stanisław Chmiela 9247f3cf78 [eas-cli] Upgrade apple-utils to 2.1.22 (#3913)
## Summary

- [eas-cli] Upgrade `@expo/apple-utils` from `2.1.19` to `2.1.22`.
- Refresh the Yarn lockfile entry for the new package tarball.
- Add a changelog entry under the unreleased `main` section.

## Why

This picks up the latest published Apple API helpers, including recent App Store Connect pagination, SIWA, and review-related fixes from `@expo/apple-utils`.

## Validation

CI should pass.
2026-06-30 18:33:59 +02:00
Stanisław Chmiela bde331da63 [eas-cli] Fix managed tvOS env typecheck (#3920)
## Summary
- fix main typecheck after `Env` was widened to allow undefined values
- align `getManagedTvBuildSettings` with the shared `Env` type instead of requiring `Record<string, string>`

## Test plan

CI should pass.
2026-06-30 12:13:25 +00:00
Stanisław Chmiela fd055f08b3 [eas-build-job] Allow undefined env values (#3900)
## Summary

Widens the shared build `Env` type to allow `undefined` values, matching Node/process env semantics where undefined entries can represent absent values.

## Details

- Changes `Env` to `Record<string, string | undefined>` in `@expo/eas-build-job`.
- Allows `ctx.reportError` extras to contain undefined values for diagnostic metadata.
- Updates strict string boundaries to explicitly require values where needed, such as GraphQL IDs and static context API URLs.
- Filters undefined values out of `displayRuntimeInfo` string-only display maps.

## Validation

CI should pass.
2026-06-30 14:03:53 +02:00
Stanisław Chmiela 785d690e65 [build-tools] Enable simulator accessibility prefs before boot (#3914)
## Summary

- Add an opt-in `enable_accessibility_settings` boolean input to `eas/start_ios_simulator`.
- When enabled, call `IosSimulatorUtils.enableAccessibilitySettingsAsync` inline immediately before each `IosSimulatorUtils.startAsync` call, including cloned simulators.
- Reuse the existing `xcrun simctl list devices --json --no-escape-slashes available` wrapper so the `dataPath` from simctl JSON is used directly, then do an exact UDID/name equality check in JS. This avoids `simctl` search-term substring matches like `iPhone 17` matching `iPhone 17 Pro`.
- Treat invalid requested simulator state as `UserError`; wrap command/filesystem setup failures as `SystemError`.

## Why

These accessibility preferences help Argent and other AX-tree based tools inspect Simulator state more reliably. They can influence app/runtime accessibility behavior, so the setting is explicit and default-off rather than applied to every simulator startup.

## Maestro compatibility

`enable_accessibility_settings` defaults to `false`, so existing Maestro test runs and other `eas/start_ios_simulator` users keep the previous startup behavior unless they opt in. When enabled, the setup only writes preferences for an exact, available, shutdown simulator before `simctl bootstatus -b`. If the requested simulator is not available or not shutdown, the step fails with `UserError`; if the setup command/filesystem work fails, it fails with `SystemError`.

## Notes

- `plutil` is a standard macOS utility (`/usr/bin/plutil` on the local validation machine), so this does not add an external tool installation requirement.

## Validation

CI should pass.
2026-06-30 11:02:21 +02:00
Kudo Chien 47335f02f0 [build-tools] Fix repack AAB output path (#3892) 2026-06-30 14:38:06 +08:00
Douglas Lowder 75d9be813f [eas-cli] Resolve ApplePlatform.TV_OS for managed tvOS targets via EXPO_TV (#3907)
# Why

Non interactive builds were attempting to incorrectly verify tvOS provisioning profiles with settings for the iOS platform.

# How

Recognize when EXPO_TV env variable is set, and in that case, set the target platform to tvOS.

Fixes #3905

# Test Plan

- Tested with a real SDK 56 TV project
- New unit tests added
2026-06-29 18:32:47 -07:00
Expo CI cdaa011ce3 update CHANGELOG.md 2026-06-29 21:45:52 +00:00
41 changed files with 792 additions and 227 deletions

No files matched your search

+11 -2
View File
@@ -8,12 +8,21 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- [eas-cli] `eas integrations:posthog:connect` now supports existing PostHog user connection. ([#3895](https://github.com/expo/eas-cli/pull/3895) by [@gwdp](https://github.com/gwdp))
### 🐛 Bug fixes
- [eas-cli] Fix Free plan users being warned they had reached their build limit while still well below it. Overage warnings are now shown only for paid plans with an actual billable overage cost. ([#3882](https://github.com/expo/eas-cli/pull/3882) by [@sarahlane8](https://github.com/sarahlane8))
- [eas-cli] Select correct tvOS build target for non-interactive Apple builds when EXPO_TV env variable is set. ([#3907](https://github.com/expo/eas-cli/pull/3907) by [@douglowder](https://github.com/douglowder))
### 🧹 Chores
- [eas-cli] Bump `@expo/apple-utils` to `2.1.22`. ([#3913](https://github.com/expo/eas-cli/pull/3913) by [@sjchmiela](https://github.com/sjchmiela))
## [20.5.0](https://github.com/expo/eas-cli/releases/tag/v20.5.0) - 2026-06-29
### 🎉 New features
- [eas-cli] `eas integrations:posthog:connect` now supports existing PostHog user connection. ([#3895](https://github.com/expo/eas-cli/pull/3895) by [@gwdp](https://github.com/gwdp))
## [20.4.0](https://github.com/expo/eas-cli/releases/tag/v20.4.0) - 2026-06-25
### 🎉 New features
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "20.5.0",
"version": "20.5.1",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@expo/build-tools",
"version": "20.4.0",
"version": "20.5.1",
"bugs": "https://github.com/expo/eas-cli/issues",
"license": "BUSL-1.1",
"author": "Expo <[email protected]>",
@@ -38,14 +38,14 @@
"@expo/config": "55.0.10",
"@expo/config-plugins": "55.0.7",
"@expo/downloader": "20.0.0",
"@expo/eas-build-job": "20.1.0",
"@expo/eas-build-job": "20.5.1",
"@expo/env": "^0.4.0",
"@expo/logger": "20.0.0",
"@expo/package-manager": "1.9.10",
"@expo/plist": "^0.2.0",
"@expo/results": "^1.0.0",
"@expo/spawn-async": "1.7.2",
"@expo/steps": "20.1.0",
"@expo/steps": "20.5.1",
"@expo/template-file": "20.0.0",
"@expo/turtle-spawn": "20.0.0",
"@expo/xcpretty": "^4.3.1",
@@ -233,7 +233,7 @@ async function uploadProjectMetadataAsync(
}
`),
{
buildId: ctx.env.EAS_BUILD_ID,
buildId: nullthrows(ctx.env.EAS_BUILD_ID, 'EAS_BUILD_ID is not set'),
projectMetadataFile: {
type: 'GCS',
bucketKey: uploadSession.bucketKey,
+2 -2
View File
@@ -63,7 +63,7 @@ export interface BuildContextOptions {
reportError?: (
msg: string,
err?: Error,
options?: { tags?: Record<string, string>; extras?: Record<string, string> }
options?: { tags?: Record<string, string>; extras?: Record<string, string | undefined> }
) => void;
skipNativeBuild?: boolean;
metadata?: Metadata;
@@ -80,7 +80,7 @@ export class BuildContext<TJob extends Job = Job> {
public readonly reportError?: (
msg: string,
err?: Error,
options?: { tags?: Record<string, string>; extras?: Record<string, string> }
options?: { tags?: Record<string, string>; extras?: Record<string, string | undefined> }
) => void;
public readonly skipNativeBuild?: boolean;
public readonly expoApiV2BaseUrl?: string;
+1 -1
View File
@@ -93,7 +93,7 @@ export async function runFastlane(
cwd,
}: {
logger?: bunyan;
env?: Record<string, string>;
env?: Env;
cwd?: string;
} = {}
): Promise<SpawnResult> {
@@ -27,7 +27,7 @@ describe(createRepackBuildFunction, () => {
vol.reset();
});
it('should set the output path for successful repack', async () => {
it('should set generated output path for successful repack', async () => {
const repack = createRepackBuildFunction();
const repackStep = repack.createBuildStepFromFunctionCall(
createGlobalContextMock({
@@ -38,14 +38,33 @@ describe(createRepackBuildFunction, () => {
{
callInputs: {
platform: 'ios',
source_app_path: '/path/to/source_app',
output_path: '/path/to/output_app',
source_app_path: '/path/to/source_app.ipa',
},
}
);
await repackStep.executeAsync();
expect(repackStep.outputById['output_path'].value).toBe('/path/to/output_app');
expect(repackStep.outputById['output_path'].value).toMatch(/repacked-.*\.ipa$/);
});
it('should rename generated aab output path to apk', async () => {
const repack = createRepackBuildFunction();
const repackStep = repack.createBuildStepFromFunctionCall(
createGlobalContextMock({
staticContextContent: {
job: createTestAndroidJob(),
},
}),
{
callInputs: {
platform: 'android',
source_app_path: '/path/to/source_app.aab',
},
}
);
await repackStep.executeAsync();
expect(repackStep.outputById['output_path'].value).toMatch(/repacked-.*\.apk$/);
});
it('should throw for unsupported platforms', async () => {
@@ -15,6 +15,7 @@ jest.mock('../../../utils/IosSimulatorUtils', () => ({
getAvailableDevicesAsync: jest.fn(),
getDeviceAsync: jest.fn(),
cloneAsync: jest.fn(),
enableAccessibilitySettingsAsync: jest.fn(),
startAsync: jest.fn(),
waitForReadyAsync: jest.fn(),
disableApsdAsync: jest.fn(),
@@ -34,15 +35,59 @@ function createStep(callInputs?: Record<string, unknown>) {
describe(createStartIosSimulatorBuildFunction, () => {
beforeEach(() => {
jest.clearAllMocks();
mockedSpawn.mockResolvedValue({ stdout: '', stderr: '' } as any);
mockedUtils.getAvailableDevicesAsync.mockResolvedValue([]);
mockedUtils.getDeviceAsync.mockResolvedValue(null);
mockedUtils.cloneAsync.mockResolvedValue(undefined);
mockedUtils.enableAccessibilitySettingsAsync.mockResolvedValue(undefined);
mockedUtils.startAsync.mockResolvedValue({ udid: 'test-udid' as any });
mockedUtils.waitForReadyAsync.mockResolvedValue(undefined);
mockedUtils.disableApsdAsync.mockResolvedValue(undefined);
});
it('does not enable accessibility settings by default', async () => {
await createStep({ device_identifier: 'iPhone 15' }).executeAsync();
expect(mockedUtils.enableAccessibilitySettingsAsync).not.toHaveBeenCalled();
expect(mockedUtils.startAsync).toHaveBeenCalledWith({
deviceIdentifier: 'iPhone 15',
env: expect.any(Object),
});
});
it('enables accessibility settings before starting the main device and every clone when requested', async () => {
mockedUtils.startAsync
.mockResolvedValueOnce({ udid: 'base' as any })
.mockResolvedValueOnce({ udid: 'clone-1' as any })
.mockResolvedValueOnce({ udid: 'clone-2' as any });
await createStep({
device_identifier: 'iPhone 15',
count: 2,
enable_accessibility_settings: true,
}).executeAsync();
expect(mockedUtils.enableAccessibilitySettingsAsync).toHaveBeenCalledWith({
deviceIdentifier: 'iPhone 15',
env: expect.any(Object),
});
expect(mockedUtils.enableAccessibilitySettingsAsync).toHaveBeenCalledWith({
deviceIdentifier: 'eas-simulator-1',
env: expect.any(Object),
});
expect(mockedUtils.enableAccessibilitySettingsAsync).toHaveBeenCalledWith({
deviceIdentifier: 'eas-simulator-2',
env: expect.any(Object),
});
for (const [callIndex] of mockedUtils.startAsync.mock.calls.entries()) {
const enableCallOrder =
mockedUtils.enableAccessibilitySettingsAsync.mock.invocationCallOrder[callIndex];
const startCallOrder = mockedUtils.startAsync.mock.invocationCallOrder[callIndex];
expect(enableCallOrder).toBeLessThan(startCallOrder);
}
});
it('disables apsd on the main device and every clone', async () => {
mockedUtils.startAsync
.mockResolvedValueOnce({ udid: 'base' as any })
@@ -1,6 +1,7 @@
import { asyncResult } from '@expo/results';
import { BuildFunction, BuildStepInput, BuildStepInputValueTypeName } from '@expo/steps';
import { Sentry } from '../../sentry';
import { retryOnDNSFailure } from '../../utils/retryOnDNSFailure';
export function createSubmissionEntityFunction(): BuildFunction {
@@ -54,18 +55,42 @@ export function createSubmissionEntityFunction(): BuildFunction {
const robotAccessToken = stepsCtx.global.staticContext.job.secrets?.robotAccessToken;
if (!robotAccessToken) {
stepsCtx.logger.error('Failed to create submission entity: no robot access token found');
Sentry.capture('Failed to create submission entity: missing robot access token');
return;
}
const buildId = inputs.build_id.value;
if (!buildId) {
stepsCtx.logger.error('Failed to create submission entity: no build ID provided');
Sentry.capture('Failed to create submission entity: missing build ID', {
extras: {
buildId,
},
});
return;
}
const workflowJobId = stepsCtx.global.env.__WORKFLOW_JOB_ID;
if (!workflowJobId) {
stepsCtx.logger.error('Failed to create submission entity: no workflow job ID found');
Sentry.capture('Failed to create submission entity: missing workflow job ID', {
extras: {
buildId,
workflowJobId,
},
});
return;
}
const expoApiServerURL = stepsCtx.global.staticContext.expoApiServerURL;
if (!expoApiServerURL) {
stepsCtx.logger.error('Failed to create submission entity: no Expo API server URL found');
Sentry.capture('Failed to create submission entity: missing Expo API server URL', {
extras: {
buildId,
workflowJobId,
},
});
return;
}
@@ -83,7 +108,7 @@ export function createSubmissionEntityFunction(): BuildFunction {
try {
const response = await retryOnDNSFailure(fetch)(
new URL('/v2/app-store-submissions/', stepsCtx.global.staticContext.expoApiServerURL),
new URL('/v2/app-store-submissions/', expoApiServerURL),
{
method: 'POST',
headers: {
@@ -1,4 +1,4 @@
import { UserError } from '@expo/eas-build-job';
import { SystemError } from '@expo/eas-build-job';
import { bunyan } from '@expo/logger';
import { asyncResult } from '@expo/results';
import {
@@ -56,18 +56,23 @@ export function createDownloadArtifactFunction(): BuildFunction {
const interpolationContext = stepsCtx.global.getInterpolationContext();
if (!('workflow' in interpolationContext)) {
throw new UserError(
'EAS_DOWNLOAD_ARTIFACT_NO_WORKFLOW',
'No workflow found in the interpolation context.'
);
throw new SystemError('No workflow found in the interpolation context.', {
trackingCode: 'EAS_DOWNLOAD_ARTIFACT_NO_WORKFLOW',
});
}
const robotAccessToken = stepsCtx.global.staticContext.job.secrets?.robotAccessToken;
if (!robotAccessToken) {
throw new UserError(
'EAS_DOWNLOAD_ARTIFACT_NO_ROBOT_ACCESS_TOKEN',
'No robot access token found in the job secrets.'
);
throw new SystemError('No robot access token found in the job secrets.', {
trackingCode: 'EAS_DOWNLOAD_ARTIFACT_NO_ROBOT_ACCESS_TOKEN',
});
}
const expoApiServerURL = stepsCtx.global.staticContext.expoApiServerURL;
if (!expoApiServerURL) {
throw new SystemError('Missing Expo API server URL.', {
trackingCode: 'EAS_DOWNLOAD_ARTIFACT_NO_EXPO_API_SERVER_URL',
});
}
const workflowRunId = interpolationContext.workflow.id;
@@ -82,7 +87,7 @@ export function createDownloadArtifactFunction(): BuildFunction {
const { artifactPath } = await downloadArtifactAsync({
logger,
workflowRunId,
expoApiServerURL: stepsCtx.global.staticContext.expoApiServerURL,
expoApiServerURL,
robotAccessToken,
params,
});
@@ -42,11 +42,6 @@ export function createRepackBuildFunction(): BuildFunction {
required: false,
allowedValueTypeName: BuildStepInputValueTypeName.STRING,
}),
BuildStepInput.createProvider({
id: 'output_path',
allowedValueTypeName: BuildStepInputValueTypeName.STRING,
required: false,
}),
BuildStepInput.createProvider({
id: 'embed_bundle_assets',
allowedValueTypeName: BuildStepInputValueTypeName.BOOLEAN,
@@ -109,9 +104,10 @@ export function createRepackBuildFunction(): BuildFunction {
stepsCtx.logger.info(`Created temporary working directory: ${workingDirectory}`);
const sourceAppPath = inputs.source_app_path.value as string;
const outputPath =
(inputs.output_path.value as string) ??
path.join(tmpDir, `repacked-${randomUUID()}${path.extname(sourceAppPath)}`);
const outputPath = createOutputPath({
sourceAppPath,
tmpDir,
});
const exportEmbedOptions = inputs.embed_bundle_assets.value
? {
sourcemapOutput: undefined,
@@ -202,6 +198,21 @@ export function createRepackBuildFunction(): BuildFunction {
});
}
function createOutputPath({
sourceAppPath,
tmpDir,
}: {
sourceAppPath: string;
tmpDir: string;
}): string {
const outputPath = path.join(tmpDir, `repacked-${randomUUID()}${path.extname(sourceAppPath)}`);
const extension = path.extname(outputPath);
if (extension.toLowerCase() !== '.aab') {
return outputPath;
}
return `${outputPath.slice(0, -extension.length)}.apk`;
}
/**
* Install `@expo/repack-app` in a sandbox directory and import it.
*/
@@ -69,6 +69,10 @@ export function createRestoreCacheFunction(): BuildFunction {
.filter(key => key !== '');
const jobId = nullthrows(env.EAS_BUILD_ID, 'EAS_BUILD_ID is not set');
const expoApiServerURL = nullthrows(
stepsCtx.global.staticContext.expoApiServerURL,
'expoApiServerURL is not set'
);
const robotAccessToken = nullthrows(
stepsCtx.global.staticContext.job.secrets?.robotAccessToken,
'robotAccessToken is not set'
@@ -77,7 +81,7 @@ export function createRestoreCacheFunction(): BuildFunction {
const { archivePath, matchedKey } = await downloadCacheAsync({
logger,
jobId,
expoApiServerURL: stepsCtx.global.staticContext.expoApiServerURL,
expoApiServerURL,
robotAccessToken,
paths,
key,
@@ -43,6 +43,10 @@ export function createSaveCacheFunction(): BuildFunction {
.filter(path => path.length > 0);
const key = z.string().parse(inputs.key.value);
const jobId = nullthrows(env.EAS_BUILD_ID, 'EAS_BUILD_ID is not set');
const expoApiServerURL = nullthrows(
stepsCtx.global.staticContext.expoApiServerURL,
'expoApiServerURL is not set'
);
const robotAccessToken = nullthrows(
stepsCtx.global.staticContext.job.secrets?.robotAccessToken,
'robotAccessToken is not set'
@@ -61,7 +65,7 @@ export function createSaveCacheFunction(): BuildFunction {
await uploadPublicCacheAsync({
logger,
jobId,
expoApiServerURL: stepsCtx.global.staticContext.expoApiServerURL,
expoApiServerURL,
robotAccessToken,
archivePath,
key,
@@ -73,7 +77,7 @@ export function createSaveCacheFunction(): BuildFunction {
await uploadCacheAsync({
logger,
jobId,
expoApiServerURL: stepsCtx.global.staticContext.expoApiServerURL,
expoApiServerURL,
robotAccessToken,
archivePath,
key,
@@ -31,6 +31,12 @@ export function createStartIosSimulatorBuildFunction(): BuildFunction {
defaultValue: 1,
allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,
}),
BuildStepInput.createProvider({
id: 'enable_accessibility_settings',
required: false,
defaultValue: false,
allowedValueTypeName: BuildStepInputValueTypeName.BOOLEAN,
}),
],
fn: async ({ logger }, { inputs, env }) => {
try {
@@ -55,11 +61,18 @@ export function createStartIosSimulatorBuildFunction(): BuildFunction {
| undefined;
const originalDeviceIdentifier =
deviceIdentifierInput ?? (await findMostGenericIphoneUuidAsync({ env }));
const enableAccessibilitySettings = Boolean(inputs.enable_accessibility_settings.value);
if (!originalDeviceIdentifier) {
throw new Error('Could not find an iPhone among available simulator devices.');
}
if (enableAccessibilitySettings) {
await IosSimulatorUtils.enableAccessibilitySettingsAsync({
deviceIdentifier: originalDeviceIdentifier,
env,
});
}
const { udid } = await IosSimulatorUtils.startAsync({
deviceIdentifier: originalDeviceIdentifier,
env,
@@ -97,6 +110,12 @@ export function createStartIosSimulatorBuildFunction(): BuildFunction {
env,
});
if (enableAccessibilitySettings) {
await IosSimulatorUtils.enableAccessibilitySettingsAsync({
deviceIdentifier: cloneDeviceName,
env,
});
}
const { udid: cloneUdid } = await IosSimulatorUtils.startAsync({
deviceIdentifier: cloneDeviceName,
env,
@@ -1,3 +1,4 @@
import { ExpoError, SystemError, UserError } from '@expo/eas-build-job';
import spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';
import fs from 'node:fs';
import os from 'node:os';
@@ -92,6 +93,67 @@ export namespace IosSimulatorUtils {
});
}
export async function enableAccessibilitySettingsAsync({
deviceIdentifier,
env,
}: {
deviceIdentifier: IosSimulatorUuid | IosSimulatorName;
env: NodeJS.ProcessEnv;
}): Promise<void> {
try {
const devices = await getAvailableDevicesAsync({ env, filter: 'available' });
const device = devices.find(
device =>
device.isAvailable &&
(device.udid === deviceIdentifier || device.name === deviceIdentifier)
);
if (!device) {
throw new UserError(
'EAS_IOS_SIMULATOR_NOT_FOUND',
`Failed to find available iOS Simulator "${deviceIdentifier}" to update accessibility settings.`
);
}
if (device.state !== 'Shutdown') {
throw new UserError(
'EAS_IOS_SIMULATOR_NOT_SHUTDOWN',
`Expected iOS Simulator "${deviceIdentifier}" to be shutdown before updating accessibility settings, but it is ${device.state}.`
);
}
const plistPath = path.join(
device.dataPath,
'Library',
'Preferences',
'com.apple.Accessibility.plist'
);
await fs.promises.mkdir(path.dirname(plistPath), { recursive: true });
const plistExists = await fs.promises
.access(plistPath)
.then(() => true)
.catch(() => false);
if (!plistExists) {
await spawn('plutil', ['-create', 'binary1', plistPath], { env });
}
for (const key of [
'AutomationEnabled',
'IgnoreAXServerEntitlements',
'AccessibilityEnabled',
'ApplicationAccessibilityEnabled',
]) {
await spawn('plutil', ['-replace', key, '-bool', 'true', plistPath], { env });
}
} catch (err) {
if (err instanceof ExpoError) {
throw err;
}
throw new SystemError('Failed to update iOS Simulator accessibility settings.', {
cause: err,
});
}
}
export async function startAsync({
deviceIdentifier,
env,
@@ -1,3 +1,4 @@
import { SystemError, UserError } from '@expo/eas-build-job';
import spawn from '@expo/turtle-spawn';
import os from 'node:os';
import path from 'node:path';
@@ -18,9 +19,143 @@ const mockedSpawn = jest.mocked(spawn);
describe('IosSimulatorUtils', () => {
beforeEach(() => {
mockedSpawn.mockReset();
mockedSpawn.mockResolvedValue({ stdout: '', stderr: '' } as any);
});
describe(IosSimulatorUtils.startAsync, () => {
it('waits for boot completion without writing accessibility prefs', async () => {
mockedSpawn.mockImplementation((async (command: string, args: string[]) => {
if (command === 'xcrun' && args.join(' ') === 'simctl bootstatus test-udid -b') {
return {
stdout: 'Monitoring boot status for iPhone 15 (test-udid).\n',
stderr: '',
} as any;
}
return { stdout: '', stderr: '' } as any;
}) as any);
await IosSimulatorUtils.startAsync({
deviceIdentifier: 'test-udid' as any,
env: process.env,
});
expect(mockedSpawn).not.toHaveBeenCalledWith(
'xcrun',
['simctl', 'list', 'devices', '--json', '--no-escape-slashes', 'test-udid'],
expect.anything()
);
expect(mockedSpawn).not.toHaveBeenCalledWith('plutil', expect.anything(), expect.anything());
});
});
describe(IosSimulatorUtils.enableAccessibilitySettingsAsync, () => {
function device(overrides: Record<string, unknown> = {}) {
return {
dataPath: '/tmp/eas-test-simulator-data',
dataPathSize: 1,
logPath: '/tmp/eas-test-simulator-logs',
udid: 'test-udid',
isAvailable: true,
deviceTypeIdentifier: 'com.apple.CoreSimulator.SimDeviceType.iPhone-15',
state: 'Shutdown',
name: 'iPhone 15',
...overrides,
};
}
function mockAvailableDevices(devices: Record<string, unknown>[]) {
mockedSpawn.mockImplementation((async (command: string, args: string[]) => {
if (
command === 'xcrun' &&
args.join(' ') === 'simctl list devices --json --no-escape-slashes available'
) {
return {
stdout: JSON.stringify({
devices: {
'com.apple.CoreSimulator.SimRuntime.iOS-18-0': devices,
},
}),
stderr: '',
} as any;
}
return { stdout: '', stderr: '' } as any;
}) as any);
}
it('writes accessibility prefs for an exact shutdown simulator match', async () => {
mockAvailableDevices([
device({
udid: 'test-udid-pro',
name: 'iPhone 17 Pro',
dataPath: '/tmp/eas-test-simulator-data-pro',
}),
device({ name: 'iPhone 17' }),
]);
await expect(
IosSimulatorUtils.enableAccessibilitySettingsAsync({
deviceIdentifier: 'iPhone 17' as any,
env: process.env,
})
).resolves.toBeUndefined();
for (const key of [
'AutomationEnabled',
'IgnoreAXServerEntitlements',
'AccessibilityEnabled',
'ApplicationAccessibilityEnabled',
]) {
expect(mockedSpawn).toHaveBeenCalledWith(
'plutil',
[
'-replace',
key,
'-bool',
'true',
'/tmp/eas-test-simulator-data/Library/Preferences/com.apple.Accessibility.plist',
],
{ env: process.env }
);
}
});
it('throws UserError when no available simulator exactly matches the identifier', async () => {
mockAvailableDevices([device({ name: 'iPhone 17 Pro' })]);
await expect(
IosSimulatorUtils.enableAccessibilitySettingsAsync({
deviceIdentifier: 'iPhone 17' as any,
env: process.env,
})
).rejects.toThrow(UserError);
expect(mockedSpawn).not.toHaveBeenCalledWith('plutil', expect.anything(), expect.anything());
});
it('throws UserError when the matched simulator is already booted', async () => {
mockAvailableDevices([device({ state: 'Booted' })]);
await expect(
IosSimulatorUtils.enableAccessibilitySettingsAsync({
deviceIdentifier: 'test-udid' as any,
env: process.env,
})
).rejects.toThrow(UserError);
});
it('throws SystemError when pre-boot accessibility setup fails', async () => {
mockedSpawn.mockRejectedValue(new Error('Failed to list simulators'));
await expect(
IosSimulatorUtils.enableAccessibilitySettingsAsync({
deviceIdentifier: 'test-udid' as any,
env: process.env,
})
).rejects.toThrow(SystemError);
});
});
describe(IosSimulatorUtils.waitForReadyAsync, () => {
it('takes the readiness screenshot into a writable temp file, not /dev/null', async () => {
await IosSimulatorUtils.waitForReadyAsync({
@@ -104,4 +104,33 @@ describe(expoUpdates.configureExpoUpdatesIfInstalledAsync, () => {
expect(iosSetChannelNativelyAsync).toBeCalledTimes(1);
expect(getExpoUpdatesPackageVersionIfInstalledAsync).toBeCalledTimes(1);
});
it('does not fail on missing EAS_BUILD_ID when logging fingerprint diffs', async () => {
jest.mocked(getExpoUpdatesPackageVersionIfInstalledAsync).mockResolvedValue('0.18.0');
const warn = jest.fn();
const managedCtx: BuildContext<BuildJob> = {
appConfig: {},
env: {},
job: {
platform: Platform.IOS,
},
logger: { warn },
metadata: {
runtimeVersion: 'runtime-version-from-local-machine',
},
getReactNativeProjectDirectory: () => '/app',
} as any;
await expect(
expoUpdates.configureExpoUpdatesIfInstalledAsync(managedCtx, {
resolvedRuntimeVersion: 'runtime-version-from-eas-build',
resolvedFingerprintSources: [],
})
).rejects.toThrow(
'Runtime version calculated on local machine not equal to runtime version calculated during build.'
);
expect(warn).toHaveBeenCalledWith('Skipping fingerprint diff because EAS_BUILD_ID is not set');
});
});
@@ -243,6 +243,12 @@ async function logDiffFingerprints({
ctx: BuildContext<BuildJob>;
}): Promise<void> {
const { resolvedRuntimeVersion, resolvedFingerprintSources } = resolvedRuntime;
const buildId = ctx.env.EAS_BUILD_ID;
if (!buildId) {
ctx.logger.warn('Skipping fingerprint diff because EAS_BUILD_ID is not set');
return;
}
const fingerprintInfo = await ctx.graphqlClient
.query(
@@ -257,7 +263,7 @@ async function logDiffFingerprints({
}
}
`),
{ id: ctx.env.EAS_BUILD_ID }
{ id: buildId }
)
.toPromise();
@@ -1,6 +1,6 @@
{
"name": "create-eas-build-function",
"version": "20.1.0",
"version": "20.5.1",
"description": "Create functions for use in EAS Build custom builds.",
"keywords": [
"expo",
@@ -35,7 +35,7 @@
"clean": "rimraf ./build/ \"*.tsbuildinfo\""
},
"dependencies": {
"@expo/steps": "20.1.0"
"@expo/steps": "20.5.1"
},
"devDependencies": {
"@expo/package-manager": "1.9.10",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@expo/eas-build-job",
"version": "20.1.0",
"version": "20.5.1",
"bugs": "https://github.com/expo/eas-cli/issues",
"license": "MIT",
"author": "Expo <[email protected]>",
@@ -1,4 +1,18 @@
import { StaticWorkflowInterpolationContextZ } from '../common';
import { EnvSchema, StaticWorkflowInterpolationContextZ } from '../common';
describe('EnvSchema', () => {
it('accepts explicit undefined values', () => {
const env = {
DEFINED_ENV: 'value',
UNDEFINED_ENV: undefined,
};
const { value, error } = EnvSchema.validate(env);
expect(error).toBeUndefined();
expect(value).toEqual(env);
});
});
describe('StaticWorkflowInterpolationContextZ', () => {
it('accepts app and account context', () => {
+2 -2
View File
@@ -115,8 +115,8 @@ export const ArchiveSourceSchemaZ = z.discriminatedUnion('type', [
}),
]);
export type Env = Record<string, string>;
export const EnvSchema = Joi.object().pattern(Joi.string(), Joi.string());
export type Env = Record<string, string | undefined>;
export const EnvSchema = Joi.object().pattern(Joi.string(), Joi.string().optional());
export type EnvironmentSecret = {
name: string;
+1 -1
View File
@@ -11,7 +11,7 @@ type StaticJobOnlyInterpolationContext = {
outputs: Record<string, string | undefined>;
}
>;
expoApiServerURL: string;
expoApiServerURL: string | undefined;
};
export type StaticJobInterpolationContext =
+114 -114
View File
@@ -207,7 +207,7 @@ DESCRIPTION
view the audit logs for an account
```
_See code: [packages/eas-cli/src/commands/account/audit.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/account/audit.ts)_
_See code: [packages/eas-cli/src/commands/account/audit.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/account/audit.ts)_
## `eas account:login`
@@ -228,7 +228,7 @@ ALIASES
$ eas login
```
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/account/login.ts)_
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -245,7 +245,7 @@ ALIASES
$ eas logout
```
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:usage [ACCOUNT_NAME]`
@@ -267,7 +267,7 @@ DESCRIPTION
view account usage and billing for the current cycle
```
_See code: [packages/eas-cli/src/commands/account/usage.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/account/usage.ts)_
_See code: [packages/eas-cli/src/commands/account/usage.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/account/usage.ts)_
## `eas account:view`
@@ -284,7 +284,7 @@ ALIASES
$ eas whoami
```
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/account/view.ts)_
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -298,7 +298,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -350,7 +350,7 @@ DESCRIPTION
create a branch
```
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/branch/create.ts)_
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -371,7 +371,7 @@ DESCRIPTION
delete a branch
```
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/branch/delete.ts)_
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -391,7 +391,7 @@ DESCRIPTION
list all branches
```
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/branch/list.ts)_
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -411,7 +411,7 @@ DESCRIPTION
rename a branch
```
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/branch/rename.ts)_
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -434,7 +434,7 @@ DESCRIPTION
view a branch
```
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/branch/view.ts)_
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -475,7 +475,7 @@ DESCRIPTION
start a build
```
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/index.ts)_
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -495,7 +495,7 @@ DESCRIPTION
cancel a build
```
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -513,7 +513,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
@@ -533,7 +533,7 @@ DESCRIPTION
delete a build
```
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/delete.ts)_
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/delete.ts)_
## `eas build:dev`
@@ -558,7 +558,7 @@ DESCRIPTION
run dev client simulator/emulator build with matching fingerprint or create a new one
```
_See code: [packages/eas-cli/src/commands/build/dev.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/dev.ts)_
_See code: [packages/eas-cli/src/commands/build/dev.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/dev.ts)_
## `eas build:download`
@@ -585,7 +585,7 @@ DESCRIPTION
download a simulator/emulator build by build ID or fingerprint hash
```
_See code: [packages/eas-cli/src/commands/build/download.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/download.ts)_
_See code: [packages/eas-cli/src/commands/build/download.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/download.ts)_
## `eas build:inspect`
@@ -623,7 +623,7 @@ DESCRIPTION
inspect the state of the project at specific build stages, useful for troubleshooting
```
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/inspect.ts)_
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -663,7 +663,7 @@ DESCRIPTION
list all builds for your project
```
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/list.ts)_
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -693,7 +693,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/resign.ts)_
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -721,7 +721,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/run.ts)_
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -773,7 +773,7 @@ DESCRIPTION
get the latest version from EAS servers
```
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/version/get.ts)_
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -791,7 +791,7 @@ DESCRIPTION
update version of an app
```
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/version/set.ts)_
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -809,7 +809,7 @@ DESCRIPTION
update a version in native code with a value stored on EAS servers
```
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/version/sync.ts)_
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -826,7 +826,7 @@ DESCRIPTION
view a build for your project
```
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/build/view.ts)_
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -847,7 +847,7 @@ DESCRIPTION
create a channel
```
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/create.ts)_
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:delete [NAME]`
@@ -868,7 +868,7 @@ DESCRIPTION
Delete a channel
```
_See code: [packages/eas-cli/src/commands/channel/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/delete.ts)_
_See code: [packages/eas-cli/src/commands/channel/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/delete.ts)_
## `eas channel:edit [NAME]`
@@ -890,7 +890,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/edit.ts)_
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:insights`
@@ -914,7 +914,7 @@ DESCRIPTION
display adoption, crash, and unique-user insights for a channel + runtime version
```
_See code: [packages/eas-cli/src/commands/channel/insights.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/insights.ts)_
_See code: [packages/eas-cli/src/commands/channel/insights.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/insights.ts)_
## `eas channel:list`
@@ -934,7 +934,7 @@ DESCRIPTION
list all channels
```
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/list.ts)_
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:pause [NAME]`
@@ -956,7 +956,7 @@ DESCRIPTION
pause a channel to stop it from sending updates
```
_See code: [packages/eas-cli/src/commands/channel/pause.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/pause.ts)_
_See code: [packages/eas-cli/src/commands/channel/pause.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/pause.ts)_
## `eas channel:resume [NAME]`
@@ -978,7 +978,7 @@ DESCRIPTION
resume a channel to start sending updates
```
_See code: [packages/eas-cli/src/commands/channel/resume.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/resume.ts)_
_See code: [packages/eas-cli/src/commands/channel/resume.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/resume.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -1013,7 +1013,7 @@ DESCRIPTION
Roll a new branch out on a channel incrementally.
```
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/rollout.ts)_
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -1036,7 +1036,7 @@ DESCRIPTION
view a channel
```
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/channel/view.ts)_
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -1057,7 +1057,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/config.ts)_
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -1074,7 +1074,7 @@ DESCRIPTION
manage credentials
```
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/credentials/index.ts)_
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/credentials/index.ts)_
## `eas credentials:configure-build`
@@ -1092,7 +1092,7 @@ DESCRIPTION
Set up credentials for building your project.
```
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/credentials/configure-build.ts)_
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/credentials/configure-build.ts)_
## `eas deploy [options]`
@@ -1121,7 +1121,7 @@ ALIASES
$ eas worker:deploy
```
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/deploy/index.ts)_
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/deploy/index.ts)_
## `eas deploy:alias`
@@ -1146,7 +1146,7 @@ ALIASES
$ eas deploy:promote
```
_See code: [packages/eas-cli/src/commands/deploy/alias/index.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/deploy/alias/index.ts)_
_See code: [packages/eas-cli/src/commands/deploy/alias/index.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/deploy/alias/index.ts)_
## `eas deploy:alias:delete [ALIAS_NAME]`
@@ -1167,7 +1167,7 @@ ALIASES
$ eas worker:alias:delete
```
_See code: [packages/eas-cli/src/commands/deploy/alias/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/deploy/alias/delete.ts)_
_See code: [packages/eas-cli/src/commands/deploy/alias/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/deploy/alias/delete.ts)_
## `eas deploy:delete [DEPLOYMENT_ID]`
@@ -1188,7 +1188,7 @@ ALIASES
$ eas worker:delete
```
_See code: [packages/eas-cli/src/commands/deploy/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/deploy/delete.ts)_
_See code: [packages/eas-cli/src/commands/deploy/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/deploy/delete.ts)_
## `eas deploy:promote`
@@ -1225,7 +1225,7 @@ DESCRIPTION
register new Apple Devices to use for internal distribution
```
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/device/create.ts)_
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -1245,7 +1245,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/device/delete.ts)_
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -1266,7 +1266,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/device/list.ts)_
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -1287,7 +1287,7 @@ DESCRIPTION
rename a registered device
```
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/device/rename.ts)_
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -1301,7 +1301,7 @@ DESCRIPTION
view a device for your project
```
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/device/view.ts)_
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -1315,7 +1315,7 @@ DESCRIPTION
display environment info
```
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas env:create [ENVIRONMENT]`
@@ -1347,7 +1347,7 @@ DESCRIPTION
create an environment variable for the current project or account
```
_See code: [packages/eas-cli/src/commands/env/create.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/create.ts)_
_See code: [packages/eas-cli/src/commands/env/create.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/create.ts)_
## `eas env:delete [ENVIRONMENT]`
@@ -1373,7 +1373,7 @@ DESCRIPTION
delete an environment variable for the current project or account
```
_See code: [packages/eas-cli/src/commands/env/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/delete.ts)_
_See code: [packages/eas-cli/src/commands/env/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/delete.ts)_
## `eas env:exec ENVIRONMENT BASH_COMMAND`
@@ -1395,7 +1395,7 @@ DESCRIPTION
execute a command with environment variables from the selected environment
```
_See code: [packages/eas-cli/src/commands/env/exec.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/exec.ts)_
_See code: [packages/eas-cli/src/commands/env/exec.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/exec.ts)_
## `eas env:get [ENVIRONMENT]`
@@ -1423,7 +1423,7 @@ DESCRIPTION
view an environment variable for the current project or account
```
_See code: [packages/eas-cli/src/commands/env/get.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/get.ts)_
_See code: [packages/eas-cli/src/commands/env/get.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/get.ts)_
## `eas env:list [ENVIRONMENT]`
@@ -1451,7 +1451,7 @@ DESCRIPTION
list environment variables for the current project or account
```
_See code: [packages/eas-cli/src/commands/env/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/list.ts)_
_See code: [packages/eas-cli/src/commands/env/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/list.ts)_
## `eas env:pull [ENVIRONMENT]`
@@ -1474,7 +1474,7 @@ DESCRIPTION
pull environment variables for the selected environment to .env file
```
_See code: [packages/eas-cli/src/commands/env/pull.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/pull.ts)_
_See code: [packages/eas-cli/src/commands/env/pull.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/pull.ts)_
## `eas env:push [ENVIRONMENT]`
@@ -1496,7 +1496,7 @@ DESCRIPTION
push environment variables from .env file to the selected environment
```
_See code: [packages/eas-cli/src/commands/env/push.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/push.ts)_
_See code: [packages/eas-cli/src/commands/env/push.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/push.ts)_
## `eas env:update [ENVIRONMENT]`
@@ -1530,7 +1530,7 @@ DESCRIPTION
update an environment variable on the current project or account
```
_See code: [packages/eas-cli/src/commands/env/update.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/env/update.ts)_
_See code: [packages/eas-cli/src/commands/env/update.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/env/update.ts)_
## `eas fingerprint:compare [HASH1] [HASH2]`
@@ -1574,7 +1574,7 @@ EXAMPLES
$ eas fingerprint:compare <FINGERPRINT-HASH> --update-id <UPDATE-ID> # Compare fingerprint from update against provided fingerprint
```
_See code: [packages/eas-cli/src/commands/fingerprint/compare.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/fingerprint/compare.ts)_
_See code: [packages/eas-cli/src/commands/fingerprint/compare.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/fingerprint/compare.ts)_
## `eas fingerprint:generate`
@@ -1605,7 +1605,7 @@ EXAMPLES
$ eas fingerprint:generate --json --non-interactive --platform android # Output fingerprint json to stdout
```
_See code: [packages/eas-cli/src/commands/fingerprint/generate.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/fingerprint/generate.ts)_
_See code: [packages/eas-cli/src/commands/fingerprint/generate.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/fingerprint/generate.ts)_
## `eas help [COMMAND]`
@@ -1684,7 +1684,7 @@ DESCRIPTION
connect a project to an App Store Connect app
```
_See code: [packages/eas-cli/src/commands/integrations/asc/connect.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/asc/connect.ts)_
_See code: [packages/eas-cli/src/commands/integrations/asc/connect.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/asc/connect.ts)_
## `eas integrations:asc:disconnect`
@@ -1703,7 +1703,7 @@ DESCRIPTION
disconnect the current project from its App Store Connect app
```
_See code: [packages/eas-cli/src/commands/integrations/asc/disconnect.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/asc/disconnect.ts)_
_See code: [packages/eas-cli/src/commands/integrations/asc/disconnect.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/asc/disconnect.ts)_
## `eas integrations:asc:status`
@@ -1721,7 +1721,7 @@ DESCRIPTION
show the App Store Connect app link status for the current project
```
_See code: [packages/eas-cli/src/commands/integrations/asc/status.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/asc/status.ts)_
_See code: [packages/eas-cli/src/commands/integrations/asc/status.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/asc/status.ts)_
## `eas integrations:convex:connect`
@@ -1743,7 +1743,7 @@ DESCRIPTION
connect Convex to your Expo project
```
_See code: [packages/eas-cli/src/commands/integrations/convex/connect.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/convex/connect.ts)_
_See code: [packages/eas-cli/src/commands/integrations/convex/connect.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/convex/connect.ts)_
## `eas integrations:convex:dashboard`
@@ -1757,7 +1757,7 @@ DESCRIPTION
open the Convex dashboard for the linked Convex project
```
_See code: [packages/eas-cli/src/commands/integrations/convex/dashboard.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/convex/dashboard.ts)_
_See code: [packages/eas-cli/src/commands/integrations/convex/dashboard.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/convex/dashboard.ts)_
## `eas integrations:convex:project`
@@ -1771,7 +1771,7 @@ DESCRIPTION
display the Convex project linked to the current Expo app
```
_See code: [packages/eas-cli/src/commands/integrations/convex/project.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/convex/project.ts)_
_See code: [packages/eas-cli/src/commands/integrations/convex/project.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/convex/project.ts)_
## `eas integrations:convex:project:delete`
@@ -1789,7 +1789,7 @@ DESCRIPTION
remove the Convex project link for the current Expo app from EAS servers
```
_See code: [packages/eas-cli/src/commands/integrations/convex/project/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/convex/project/delete.ts)_
_See code: [packages/eas-cli/src/commands/integrations/convex/project/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/convex/project/delete.ts)_
## `eas integrations:convex:team`
@@ -1803,7 +1803,7 @@ DESCRIPTION
display Convex teams linked to the current Expo app's owner account
```
_See code: [packages/eas-cli/src/commands/integrations/convex/team.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/convex/team.ts)_
_See code: [packages/eas-cli/src/commands/integrations/convex/team.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/convex/team.ts)_
## `eas integrations:convex:team:delete [CONVEX_TEAM]`
@@ -1824,7 +1824,7 @@ DESCRIPTION
remove a Convex team link from the current Expo app owner account's EAS servers
```
_See code: [packages/eas-cli/src/commands/integrations/convex/team/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/convex/team/delete.ts)_
_See code: [packages/eas-cli/src/commands/integrations/convex/team/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/convex/team/delete.ts)_
## `eas integrations:convex:team:invite [CONVEX_TEAM]`
@@ -1844,7 +1844,7 @@ DESCRIPTION
send a Convex team invitation to your verified email address
```
_See code: [packages/eas-cli/src/commands/integrations/convex/team/invite.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/convex/team/invite.ts)_
_See code: [packages/eas-cli/src/commands/integrations/convex/team/invite.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/convex/team/invite.ts)_
## `eas integrations:posthog:connect`
@@ -1871,7 +1871,7 @@ DESCRIPTION
connect PostHog to your Expo project
```
_See code: [packages/eas-cli/src/commands/integrations/posthog/connect.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/posthog/connect.ts)_
_See code: [packages/eas-cli/src/commands/integrations/posthog/connect.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/posthog/connect.ts)_
## `eas integrations:posthog:dashboard`
@@ -1889,7 +1889,7 @@ DESCRIPTION
open the PostHog dashboard for the linked PostHog project
```
_See code: [packages/eas-cli/src/commands/integrations/posthog/dashboard.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/posthog/dashboard.ts)_
_See code: [packages/eas-cli/src/commands/integrations/posthog/dashboard.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/posthog/dashboard.ts)_
## `eas integrations:posthog:disconnect`
@@ -1908,7 +1908,7 @@ DESCRIPTION
remove the PostHog project link for the current Expo app from EAS servers
```
_See code: [packages/eas-cli/src/commands/integrations/posthog/disconnect.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/integrations/posthog/disconnect.ts)_
_See code: [packages/eas-cli/src/commands/integrations/posthog/disconnect.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/integrations/posthog/disconnect.ts)_
## `eas login`
@@ -1960,7 +1960,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/metadata/lint.ts)_
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1978,7 +1978,7 @@ DESCRIPTION
generate the local store configuration from the app stores
```
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/metadata/pull.ts)_
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1996,7 +1996,7 @@ DESCRIPTION
sync the local store configuration to the app stores
```
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/metadata/push.ts)_
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas new [PATH]`
@@ -2055,7 +2055,7 @@ DESCRIPTION
arguments, a list of the available event names and associated event counts is returned.
```
_See code: [packages/eas-cli/src/commands/observe/events.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/observe/events.ts)_
_See code: [packages/eas-cli/src/commands/observe/events.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/observe/events.ts)_
## `eas observe:metrics [METRIC]`
@@ -2090,7 +2090,7 @@ DESCRIPTION
display individual performance metric samples ordered by value
```
_See code: [packages/eas-cli/src/commands/observe/metrics.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/observe/metrics.ts)_
_See code: [packages/eas-cli/src/commands/observe/metrics.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/observe/metrics.ts)_
## `eas observe:metrics-summary`
@@ -2121,7 +2121,7 @@ DESCRIPTION
display aggregated performance metric statistics grouped by app version
```
_See code: [packages/eas-cli/src/commands/observe/metrics-summary.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/observe/metrics-summary.ts)_
_See code: [packages/eas-cli/src/commands/observe/metrics-summary.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/observe/metrics-summary.ts)_
## `eas observe:routes`
@@ -2158,7 +2158,7 @@ DESCRIPTION
display app navigation route metrics (Cold TTR, Warm TTR, TTI) grouped by route name
```
_See code: [packages/eas-cli/src/commands/observe/routes.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/observe/routes.ts)_
_See code: [packages/eas-cli/src/commands/observe/routes.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/observe/routes.ts)_
## `eas observe:session SESSIONID`
@@ -2180,7 +2180,7 @@ DESCRIPTION
display the timeline of metric and log events for a specific session
```
_See code: [packages/eas-cli/src/commands/observe/session.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/observe/session.ts)_
_See code: [packages/eas-cli/src/commands/observe/session.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/observe/session.ts)_
## `eas observe:versions`
@@ -2205,7 +2205,7 @@ DESCRIPTION
display app versions with build and update details
```
_See code: [packages/eas-cli/src/commands/observe/versions.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/observe/versions.ts)_
_See code: [packages/eas-cli/src/commands/observe/versions.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/observe/versions.ts)_
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -2235,7 +2235,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/open.ts)_
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -2249,7 +2249,7 @@ DESCRIPTION
information about the current project
```
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/project/info.ts)_
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -2272,7 +2272,7 @@ ALIASES
$ eas init
```
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/project/init.ts)_
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/project/init.ts)_
## `eas project:new [PATH]`
@@ -2296,7 +2296,7 @@ ALIASES
$ eas new
```
_See code: [packages/eas-cli/src/commands/project/new.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/project/new.ts)_
_See code: [packages/eas-cli/src/commands/project/new.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/project/new.ts)_
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -2314,7 +2314,7 @@ ALIASES
$ eas onboarding
```
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/project/onboarding.ts)_
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/project/onboarding.ts)_
## `eas submit`
@@ -2347,7 +2347,7 @@ ALIASES
$ eas build:submit
```
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -2390,7 +2390,7 @@ DESCRIPTION
publish an update group
```
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/index.ts)_
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -2411,7 +2411,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/configure.ts)_
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -2432,7 +2432,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/delete.ts)_
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:edit [GROUPID]`
@@ -2457,7 +2457,7 @@ DESCRIPTION
edit all the updates in an update group
```
_See code: [packages/eas-cli/src/commands/update/edit.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/edit.ts)_
_See code: [packages/eas-cli/src/commands/update/edit.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/edit.ts)_
## `eas update:embedded:delete ID`
@@ -2478,7 +2478,7 @@ DESCRIPTION
delete an embedded update registered with EAS Update
```
_See code: [packages/eas-cli/src/commands/update/embedded/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/embedded/delete.ts)_
_See code: [packages/eas-cli/src/commands/update/embedded/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/embedded/delete.ts)_
## `eas update:embedded:list`
@@ -2504,7 +2504,7 @@ DESCRIPTION
list embedded updates registered with EAS Update for this project
```
_See code: [packages/eas-cli/src/commands/update/embedded/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/embedded/list.ts)_
_See code: [packages/eas-cli/src/commands/update/embedded/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/embedded/list.ts)_
## `eas update:embedded:upload`
@@ -2534,7 +2534,7 @@ EXAMPLES
$ eas update:embedded:upload --platform android --bundle android/app/src/main/assets/index.android.bundle --manifest android/app/src/main/assets/app.manifest --channel production --build-id <BUILD-ID>
```
_See code: [packages/eas-cli/src/commands/update/embedded/upload.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/embedded/upload.ts)_
_See code: [packages/eas-cli/src/commands/update/embedded/upload.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/embedded/upload.ts)_
## `eas update:embedded:view ID`
@@ -2554,7 +2554,7 @@ DESCRIPTION
view details of an embedded update registered with EAS Update
```
_See code: [packages/eas-cli/src/commands/update/embedded/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/embedded/view.ts)_
_See code: [packages/eas-cli/src/commands/update/embedded/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/embedded/view.ts)_
## `eas update:insights GROUPID`
@@ -2581,7 +2581,7 @@ DESCRIPTION
display launch, crash, unique-user, and size insights for an update group
```
_See code: [packages/eas-cli/src/commands/update/insights.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/insights.ts)_
_See code: [packages/eas-cli/src/commands/update/insights.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/insights.ts)_
## `eas update:list`
@@ -2608,7 +2608,7 @@ DESCRIPTION
view the recent updates
```
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/list.ts)_
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -2646,7 +2646,7 @@ DESCRIPTION
roll back to an existing update
```
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/republish.ts)_
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:revert-update-rollout`
@@ -2674,7 +2674,7 @@ DESCRIPTION
revert a rollout update for a project
```
_See code: [packages/eas-cli/src/commands/update/revert-update-rollout.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/revert-update-rollout.ts)_
_See code: [packages/eas-cli/src/commands/update/revert-update-rollout.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/revert-update-rollout.ts)_
## `eas update:roll-back-to-embedded`
@@ -2704,7 +2704,7 @@ DESCRIPTION
roll back to the embedded update
```
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback [GROUPID]`
@@ -2736,7 +2736,7 @@ DESCRIPTION
roll back to an embedded update or an existing update
```
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/rollback.ts)_
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -2760,7 +2760,7 @@ DESCRIPTION
update group details
```
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/update/view.ts)_
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/update/view.ts)_
## `eas upload`
@@ -2781,7 +2781,7 @@ DESCRIPTION
upload a local build and generate a sharable link
```
_See code: [packages/eas-cli/src/commands/upload.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/upload.ts)_
_See code: [packages/eas-cli/src/commands/upload.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/upload.ts)_
## `eas webhook:create`
@@ -2803,7 +2803,7 @@ DESCRIPTION
create a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -2823,7 +2823,7 @@ DESCRIPTION
delete a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -2842,7 +2842,7 @@ DESCRIPTION
list webhooks
```
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -2865,7 +2865,7 @@ DESCRIPTION
update a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -2882,7 +2882,7 @@ DESCRIPTION
view a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
@@ -3003,7 +3003,7 @@ DESCRIPTION
to cancel.
```
_See code: [packages/eas-cli/src/commands/workflow/cancel.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/cancel.ts)_
_See code: [packages/eas-cli/src/commands/workflow/cancel.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/cancel.ts)_
## `eas workflow:create [NAME]`
@@ -3023,7 +3023,7 @@ DESCRIPTION
create a new workflow configuration YAML file
```
_See code: [packages/eas-cli/src/commands/workflow/create.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/create.ts)_
_See code: [packages/eas-cli/src/commands/workflow/create.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/create.ts)_
## `eas workflow:logs [ID]`
@@ -3047,7 +3047,7 @@ DESCRIPTION
If no ID is passed in, you will be prompted to select from recent workflow runs for the current project.
```
_See code: [packages/eas-cli/src/commands/workflow/logs.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/logs.ts)_
_See code: [packages/eas-cli/src/commands/workflow/logs.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/logs.ts)_
## `eas workflow:run FILE`
@@ -3087,7 +3087,7 @@ FLAG DESCRIPTIONS
Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.
```
_See code: [packages/eas-cli/src/commands/workflow/run.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/run.ts)_
_See code: [packages/eas-cli/src/commands/workflow/run.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/run.ts)_
## `eas workflow:runs`
@@ -3109,7 +3109,7 @@ DESCRIPTION
list recent workflow runs for this project, with their IDs, statuses, and timestamps
```
_See code: [packages/eas-cli/src/commands/workflow/runs.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/runs.ts)_
_See code: [packages/eas-cli/src/commands/workflow/runs.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/runs.ts)_
## `eas workflow:status [WORKFLOW_RUN_ID]`
@@ -3137,7 +3137,7 @@ FLAG DESCRIPTIONS
Exit codes: 0 = success, 11 = failure, 12 = canceled, 13 = wait aborted.
```
_See code: [packages/eas-cli/src/commands/workflow/status.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/status.ts)_
_See code: [packages/eas-cli/src/commands/workflow/status.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/status.ts)_
## `eas workflow:validate PATH`
@@ -3157,7 +3157,7 @@ DESCRIPTION
validate a workflow configuration yaml file
```
_See code: [packages/eas-cli/src/commands/workflow/validate.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/validate.ts)_
_See code: [packages/eas-cli/src/commands/workflow/validate.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/validate.ts)_
## `eas workflow:view [ID]`
@@ -3179,5 +3179,5 @@ DESCRIPTION
workflow runs for the current project.
```
_See code: [packages/eas-cli/src/commands/workflow/view.ts](https://github.com/expo/eas-cli/blob/v20.5.0/packages/eas-cli/src/commands/workflow/view.ts)_
_See code: [packages/eas-cli/src/commands/workflow/view.ts](https://github.com/expo/eas-cli/blob/v20.5.1/packages/eas-cli/src/commands/workflow/view.ts)_
<!-- commandsstop -->
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "eas-cli",
"version": "20.5.0",
"version": "20.5.1",
"description": "EAS command line tool",
"keywords": [
"cli",
@@ -44,12 +44,12 @@
"copy-new-templates": "rimraf build/commandUtils/new/templates && mkdir -p build/commandUtils/new && cp -r src/commandUtils/new/templates build/commandUtils/new"
},
"dependencies": {
"@expo/apple-utils": "2.1.19",
"@expo/apple-utils": "2.1.22",
"@expo/code-signing-certificates": "0.0.5",
"@expo/config": "55.0.10",
"@expo/config-plugins": "55.0.7",
"@expo/eas-build-job": "20.1.0",
"@expo/eas-json": "20.1.0",
"@expo/eas-build-job": "20.5.1",
"@expo/eas-json": "20.5.1",
"@expo/env": "^1.0.0",
"@expo/json-file": "8.3.3",
"@expo/logger": "20.0.0",
@@ -64,7 +64,7 @@
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.7.2",
"@expo/steps": "20.1.0",
"@expo/steps": "20.5.1",
"@expo/timeago.js": "1.0.0",
"@oclif/core": "^4.8.3",
"@oclif/plugin-autocomplete": "^3.2.40",
+2 -2
View File
@@ -1,5 +1,5 @@
import { ExpoConfig } from '@expo/config';
import { Platform, Workflow } from '@expo/eas-build-job';
import { Env, Platform, Workflow } from '@expo/eas-build-job';
import { BuildProfile, EasJson } from '@expo/eas-json';
import { LoggerLevel } from '@expo/logger';
import { NodePackageManager } from '@expo/package-manager';
@@ -65,5 +65,5 @@ export interface BuildContext<T extends Platform> {
loggerLevel?: LoggerLevel;
isVerboseLoggingEnabled: boolean;
whatToTest?: string;
env: Record<string, string>;
env: Env;
}
+2 -2
View File
@@ -1,4 +1,4 @@
import { Platform } from '@expo/eas-build-job';
import { Env, Platform } from '@expo/eas-build-job';
import { BuildProfile, EasJson, ResourceClass } from '@expo/eas-json';
import JsonFile from '@expo/json-file';
import { LoggerLevel } from '@expo/logger';
@@ -69,7 +69,7 @@ export async function createBuildContextAsync<T extends Platform>({
refreshAdHocProvisioningProfile?: boolean;
isVerboseLoggingEnabled: boolean;
whatToTest?: string;
env: Record<string, string>;
env: Env;
}): Promise<BuildContext<T>> {
const { exp, projectId } = await getDynamicPrivateProjectConfigAsync({
env,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Job, Metadata, version } from '@expo/eas-build-job';
import { Env, Job, Metadata, version } from '@expo/eas-build-job';
import spawnAsync from '@expo/spawn-async';
import { ChildProcess } from 'child_process';
import semver from 'semver';
@@ -42,7 +42,7 @@ export async function runLocalBuildAsync(
job: Job,
metadata: Metadata,
options: LocalBuildOptions,
env: Record<string, string>
env: Env
): Promise<void> {
const { command, args } = await getCommandAndArgsAsync(job, metadata);
let spinner;
+2 -2
View File
@@ -1,4 +1,4 @@
import { Platform, Workflow } from '@expo/eas-build-job';
import { Env, Platform, Workflow } from '@expo/eas-build-job';
import { createFingerprintAsync } from './cli';
import { Fingerprint } from './types';
@@ -16,7 +16,7 @@ export async function getFingerprintInfoFromLocalProjectForPlatformsAsync(
projectId: string,
vcsClient: Client,
platforms: AppPlatform[],
{ env }: { env?: Record<string, string> } = {}
{ env }: { env?: Env } = {}
): Promise<Fingerprint> {
const workflows = await resolveWorkflowPerPlatformAsync(projectDir, vcsClient);
const optionsFromWorkflow = getFingerprintOptionsFromWorkflow(platforms, workflows);
@@ -1,7 +1,12 @@
import { testTarget } from '../../../credentials/__tests__/fixtures-ios';
import { ApplePlatform } from '../../../credentials/ios/appstore/constants';
import { Target } from '../../../credentials/ios/types';
import { getApplePlatformFromDeviceFamily, getApplePlatformFromSdkRoot } from '../target';
import {
getApplePlatformFromDeviceFamily,
getApplePlatformFromSdkRoot,
getApplePlatformFromTarget,
getManagedTvBuildSettings,
} from '../target';
function getApplePlatformWithSdkRoot(sdkRoot: string): ApplePlatform | null {
const target = {
@@ -56,3 +61,64 @@ describe(getApplePlatformFromDeviceFamily, () => {
expect(getApplePlatformWithDeviceFamily('ilovecats')).toBe(null);
});
});
describe(getManagedTvBuildSettings, () => {
const originalExpoTv = process.env.EXPO_TV;
afterEach(() => {
if (originalExpoTv === undefined) {
delete process.env.EXPO_TV;
} else {
process.env.EXPO_TV = originalExpoTv;
}
});
test('returns undefined when EXPO_TV is not set in env or process.env', () => {
delete process.env.EXPO_TV;
expect(getManagedTvBuildSettings(undefined)).toBeUndefined();
expect(getManagedTvBuildSettings({})).toBeUndefined();
expect(getManagedTvBuildSettings({ EXPO_TV: '' })).toBeUndefined();
expect(getManagedTvBuildSettings({ EXPO_TV: '0' })).toBeUndefined();
expect(getManagedTvBuildSettings({ EXPO_TV: 'false' })).toBeUndefined();
expect(getManagedTvBuildSettings({ EXPO_TV: 'no' })).toBeUndefined();
});
test('returns TARGETED_DEVICE_FAMILY=3 when EXPO_TV is truthy in the env parameter (eas.json case)', () => {
delete process.env.EXPO_TV;
for (const value of ['1', 'true', 'yes', 'TRUE', 'Yes']) {
expect(getManagedTvBuildSettings({ EXPO_TV: value })).toEqual({
TARGETED_DEVICE_FAMILY: '3',
});
}
});
test('falls back to process.env when env is missing EXPO_TV (shell case)', () => {
process.env.EXPO_TV = '1';
expect(getManagedTvBuildSettings(undefined)).toEqual({ TARGETED_DEVICE_FAMILY: '3' });
expect(getManagedTvBuildSettings({})).toEqual({ TARGETED_DEVICE_FAMILY: '3' });
});
test('env-parameter EXPO_TV takes precedence over process.env (eas.json overrides shell)', () => {
process.env.EXPO_TV = '0';
expect(getManagedTvBuildSettings({ EXPO_TV: '1' })).toEqual({
TARGETED_DEVICE_FAMILY: '3',
});
process.env.EXPO_TV = '1';
expect(getManagedTvBuildSettings({ EXPO_TV: '0' })).toBeUndefined();
});
test('feeds into getApplePlatformFromTarget so managed tvOS targets resolve to TV_OS', () => {
delete process.env.EXPO_TV;
const target: Target = {
...testTarget,
buildSettings: getManagedTvBuildSettings({ EXPO_TV: '1' }),
};
expect(getApplePlatformFromTarget(target)).toBe(ApplePlatform.TV_OS);
const iosTarget: Target = {
...testTarget,
buildSettings: getManagedTvBuildSettings({}),
};
expect(getApplePlatformFromTarget(iosTarget)).toBe(ApplePlatform.IOS);
});
});
@@ -1,4 +1,5 @@
import { ExportedConfig, IOSConfig, compileModsAsync } from '@expo/config-plugins';
import { Env } from '@expo/eas-build-job';
import { JSONObject } from '@expo/json-file';
import { getPrebuildConfigAsync } from '@expo/prebuild-config';
@@ -17,7 +18,7 @@ interface Target {
export async function getManagedApplicationTargetEntitlementsAsync(
projectDir: string,
env: Record<string, string>,
env: Env,
vcsClient: Client
): Promise<JSONObject> {
let expoConfigError: any;
@@ -95,7 +96,7 @@ export async function getManagedApplicationTargetEntitlementsAsync(
async function resolveManagedApplicationTargetEntitlementsWithBundledConfigAsync(
projectDir: string,
env: Record<string, string>,
env: Env,
vcsClient: Client
): Promise<JSONObject> {
const originalProcessEnv = process.env;
+27 -2
View File
@@ -1,6 +1,6 @@
import { ExpoConfig } from '@expo/config';
import { IOSConfig, XcodeProject } from '@expo/config-plugins';
import { Platform, Workflow } from '@expo/eas-build-job';
import { Env, Platform, Workflow } from '@expo/eas-build-job';
import { JSONObject } from '@expo/json-file';
import Joi from 'joi';
import type { XCBuildConfiguration } from 'xcode';
@@ -26,7 +26,7 @@ interface UserDefinedTarget {
interface ResolveTargetOptions {
projectDir: string;
exp: ExpoConfig;
env?: Record<string, string>;
env?: Env;
xcodeBuildContext: XcodeBuildContext;
vcsClient: Client;
}
@@ -40,6 +40,28 @@ const AppExtensionsConfigSchema = Joi.array().items(
})
);
/**
* For managed projects we don't have an Xcode project to read build settings
* from, but the @react-native-tvos/config-tv plugin signals a tvOS build via
* the EXPO_TV environment variable. That variable can come from the build
* profile's `env` in eas.json (the typical case, which flows in via `env`),
* or from the shell process when the user runs `EXPO_TV=1 eas build ...`
* (which is NOT included in the merged `env` upstream, so we read
* `process.env` directly as a fallback). When set, synthesize
* TARGETED_DEVICE_FAMILY=3 so getApplePlatformFromTarget (and every
* Apple-portal flow downstream) picks TV_OS for these targets instead of
* defaulting to IOS.
*/
export function getManagedTvBuildSettings(
env: Env | undefined
): Target['buildSettings'] | undefined {
const expoTv = (env?.EXPO_TV ?? process.env.EXPO_TV ?? '').toString().toLowerCase();
if (expoTv === '1' || expoTv === 'true' || expoTv === 'yes') {
return { TARGETED_DEVICE_FAMILY: '3' };
}
return undefined;
}
export async function resolveManagedProjectTargetsAsync({
exp,
projectDir,
@@ -76,12 +98,14 @@ export async function resolveManagedProjectTargetsAsync({
);
}
const managedBuildSettings = getManagedTvBuildSettings(env);
const extensionsTargets: Target[] = appExtensions.map(extension => ({
targetName: extension.targetName,
buildConfiguration,
bundleIdentifier: extension.bundleIdentifier,
parentBundleIdentifier: extension.parentBundleIdentifier ?? applicationTargetBundleIdentifier,
entitlements: extension.entitlements ?? {},
...(managedBuildSettings && { buildSettings: managedBuildSettings }),
}));
return [
{
@@ -89,6 +113,7 @@ export async function resolveManagedProjectTargetsAsync({
bundleIdentifier: applicationTargetBundleIdentifier,
buildConfiguration,
entitlements: applicationTargetEntitlements,
...(managedBuildSettings && { buildSettings: managedBuildSettings }),
},
...extensionsTargets,
];
+2 -2
View File
@@ -1,5 +1,5 @@
import { ExpoConfig } from '@expo/config';
import { Platform } from '@expo/eas-build-job';
import { Env, Platform } from '@expo/eas-build-job';
import { SubmitProfile } from '@expo/eas-json';
import { v4 as uuidv4 } from 'uuid';
@@ -47,7 +47,7 @@ export interface SubmitArchiveFlags {
export async function createSubmissionContextAsync<T extends Platform>(params: {
archiveFlags: SubmitArchiveFlags;
credentialsCtx?: CredentialsContext;
env?: Record<string, string>;
env?: Env;
nonInteractive: boolean;
isVerboseFastlaneEnabled: boolean;
groups: string[] | undefined;
@@ -242,6 +242,26 @@ describe('maybeWarnAboutUsageOveragesAsync', () => {
expect(mockWarn).not.toHaveBeenCalled();
});
it('does not warn a Free plan below its limit even if the usage API reports an overage', async () => {
// Regression: free users with only a handful of builds were told they'd reached
// their limit because a nonzero overage row was treated as billable usage.
mockGetUsageForOverageWarningAsync.mockResolvedValue(
createMockAccountUsage({
subscriptionName: 'Free',
buildPlanMetrics: [createMockPlanMetric({ value: 6, limit: 30 })],
overageMetrics: [{ __typename: 'EstimatedOverageAndCost', id: 'o1', value: 5 }],
totalCost: 0,
})
);
await maybeWarnAboutUsageOveragesAsync({
graphqlClient: mockGraphqlClient,
accountId: 'account-id',
});
expect(mockWarn).not.toHaveBeenCalled();
});
it('handles errors gracefully', async () => {
mockGetUsageForOverageWarningAsync.mockRejectedValue(new Error('Network error'));
@@ -267,26 +287,74 @@ describe('maybeWarnAboutUsageOveragesAsync', () => {
});
describe('classifyUsageTier', () => {
const paid = { overageCostCents: 0, hasFreePlan: false };
it('returns null when usage is below threshold', () => {
expect(classifyUsageTier({ planValue: 50, limit: 100, overageCount: 0 })).toBeNull();
expect(classifyUsageTier({ planValue: 79, limit: 100, overageCount: 0 })).toBeNull();
expect(classifyUsageTier({ planValue: 50, limit: 100, overageCount: 0, ...paid })).toBeNull();
expect(classifyUsageTier({ planValue: 79, limit: 100, overageCount: 0, ...paid })).toBeNull();
});
it('returns "approaching" at >= 80% but below limit', () => {
expect(classifyUsageTier({ planValue: 80, limit: 100, overageCount: 0 })).toBe('approaching');
expect(classifyUsageTier({ planValue: 99, limit: 100, overageCount: 0 })).toBe('approaching');
expect(classifyUsageTier({ planValue: 80, limit: 100, overageCount: 0, ...paid })).toBe(
'approaching'
);
expect(classifyUsageTier({ planValue: 99, limit: 100, overageCount: 0, ...paid })).toBe(
'approaching'
);
});
it('returns "at" when planValue >= limit and no overage', () => {
expect(classifyUsageTier({ planValue: 100, limit: 100, overageCount: 0 })).toBe('at');
expect(classifyUsageTier({ planValue: 100, limit: 100, overageCount: 0, ...paid })).toBe('at');
});
it('returns "over" when any overage has been counted', () => {
expect(classifyUsageTier({ planValue: 105, limit: 100, overageCount: 5 })).toBe('over');
it('returns "over" for a paid plan with a counted, billable overage', () => {
expect(
classifyUsageTier({
planValue: 105,
limit: 100,
overageCount: 5,
overageCostCents: 750,
hasFreePlan: false,
})
).toBe('over');
});
it('prefers "over" if overage exists, regardless of planValue', () => {
expect(classifyUsageTier({ planValue: 50, limit: 100, overageCount: 1 })).toBe('over');
it('prefers "over" if a billable overage exists, regardless of planValue', () => {
expect(
classifyUsageTier({
planValue: 50,
limit: 100,
overageCount: 1,
overageCostCents: 150,
hasFreePlan: false,
})
).toBe('over');
});
it('never returns "over" for a Free plan, even if an overage is reported', () => {
// Regression: free users below their limit were shown the "reached your limit" warning
// because a nonzero overage row was treated as billable usage.
expect(
classifyUsageTier({
planValue: 6,
limit: 30,
overageCount: 5,
overageCostCents: 0,
hasFreePlan: true,
})
).toBeNull();
});
it('does not return "over" for a paid plan when the overage has no billable cost', () => {
expect(
classifyUsageTier({
planValue: 6,
limit: 30,
overageCount: 5,
overageCostCents: 0,
hasFreePlan: false,
})
).toBeNull();
});
});
@@ -35,16 +35,18 @@ export async function maybeWarnAboutUsageOveragesAsync({
const overageCount = buildMetrics.overageMetrics.reduce((sum, o) => sum + o.value, 0);
const overageCostCents = buildMetrics.totalCost;
const hasFreePlan = subscription.name === 'Free';
const tier = classifyUsageTier({
planValue: planMetric.value,
limit: planMetric.limit,
overageCount,
overageCostCents,
hasFreePlan,
});
if (!tier) {
return;
}
const hasFreePlan = subscription.name === 'Free';
displayOverageWarning({
tier,
name,
@@ -64,12 +66,22 @@ export function classifyUsageTier({
planValue,
limit,
overageCount,
overageCostCents,
hasFreePlan,
}: {
planValue: number;
limit: number;
overageCount: number;
overageCostCents: number;
hasFreePlan: boolean;
}): UsageTier | null {
if (overageCount > 0) {
// Only paid plans can incur pay-as-you-go overages, and only when there is an
// actual billable cost. Free plans are blocked at the limit and are never charged,
// so they can never be in an "over" state — a nonzero overage row (e.g. a usage
// rollup returned by the API) must not be treated as billable usage. Without this
// guard, free users well below their limit were shown a "you've reached your limit,
// upgrade to keep building" warning.
if (!hasFreePlan && overageCount > 0 && overageCostCents > 0) {
return 'over';
}
if (limit > 0 && planValue >= limit) {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@expo/eas-json",
"version": "20.1.0",
"version": "20.5.1",
"description": "A library for interacting with eas.json",
"homepage": "https://github.com/expo/eas-cli",
"bugs": "https://github.com/expo/eas-cli/issues",
@@ -32,7 +32,7 @@
},
"dependencies": {
"@babel/code-frame": "7.23.5",
"@expo/eas-build-job": "20.1.0",
"@expo/eas-build-job": "20.5.1",
"chalk": "4.1.2",
"env-string": "1.0.1",
"fs-extra": "11.2.0",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "eas-cli-local-build-plugin",
"version": "20.4.0",
"version": "20.5.1",
"description": "Tool for running EAS compatible builds on a local machine.",
"bugs": "https://github.com/expo/eas-cli/issues",
"license": "BUSL-1.1",
@@ -26,8 +26,8 @@
"clean": "rimraf node_modules dist coverage \"*.tsbuildinfo\""
},
"dependencies": {
"@expo/build-tools": "20.4.0",
"@expo/eas-build-job": "20.1.0",
"@expo/build-tools": "20.5.1",
"@expo/eas-build-job": "20.5.1",
"@expo/logger": "20.0.0",
"@expo/spawn-async": "^1.7.2",
"@expo/turtle-spawn": "20.0.0",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@expo/steps",
"version": "20.1.0",
"version": "20.5.1",
"bugs": "https://github.com/expo/eas-cli/issues",
"license": "BUSL-1.1",
"author": "Expo <[email protected]>",
@@ -27,7 +27,7 @@
"clean": "rimraf node_modules dist coverage \"*.tsbuildinfo\""
},
"dependencies": {
"@expo/eas-build-job": "20.1.0",
"@expo/eas-build-job": "20.5.1",
"@expo/logger": "20.0.0",
"@expo/spawn-async": "^1.7.2",
"arg": "^5.0.2",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@expo/worker",
"version": "20.5.0",
"version": "20.5.1",
"private": true,
"scripts": {
"start": "yarn watch",
@@ -19,16 +19,16 @@
},
"dependencies": {
"@babel/core": "7.24.7",
"@expo/build-tools": "20.4.0",
"@expo/build-tools": "20.5.1",
"@expo/config-plugins": "55.0.7",
"@expo/config-types": "55.0.5",
"@expo/downloader": "20.0.0",
"@expo/eas-build-job": "20.1.0",
"@expo/eas-build-job": "20.5.1",
"@expo/logger": "20.0.0",
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.7.2",
"@expo/steps": "20.1.0",
"@expo/steps": "20.5.1",
"@expo/template-file": "20.0.0",
"@expo/turtle-spawn": "20.0.0",
"@hapi/boom": "10.0.1",
+11 -5
View File
@@ -70,24 +70,30 @@ function printImageDescription(ctx: BuildContext<Job>): void {
function printEnvs(ctx: BuildContext<Job>): void {
const { logger, job } = ctx;
const publicEnv: Record<string, string> = {};
const secretEnv: Record<string, string> = {};
// We don't expect environment secrets to be missing from ctx.env,
// but if they do we want to see it in logs as "=undefined".
const secretEnv: Record<string, string | undefined> = {};
const instanceEnv: Record<string, string> = {};
// skip development and testing to avoid leaking local credentials from envs to bucket
if (config.env !== Environment.DEVELOPMENT && config.env !== Environment.TEST) {
Object.entries(ctx.env).forEach(([key, value]) => {
instanceEnv[key] = value;
if (value !== undefined) {
instanceEnv[key] = value;
}
});
}
Object.entries(job.builderEnvironment?.env ?? ({} as Record<string, string>)).forEach(
([key, value]) => {
Object.entries(job.builderEnvironment?.env ?? {}).forEach(([key, value]) => {
if (value !== undefined) {
publicEnv[key] = value;
delete instanceEnv[key];
}
);
});
job.secrets?.environmentSecrets?.forEach(({ name, type }) => {
if (type === EnvironmentSecretType.FILE) {
// ctx.env[name] for a FILE-typed environment secret
// should be a path to the file.
secretEnv[name] = ctx.env[name];
} else {
secretEnv[name] = '********';
Generated
+22 -22
View File
@@ -2847,23 +2847,23 @@ __metadata:
languageName: node
linkType: hard
"@expo/apple-utils@npm:2.1.19":
version: 2.1.19
resolution: "@expo/apple-utils@npm:2.1.19"
"@expo/apple-utils@npm:2.1.22":
version: 2.1.22
resolution: "@expo/apple-utils@npm:2.1.22"
bin:
apple-utils: bin.js
checksum: 10c0/42eb1038bd0906d53b37d830499c7a8ee7ec9f9b9ef4078ff898ca84cb5af1e6ac39d3a392818825151aa2ea237a44698f539b973936733350f314efff020858
checksum: 10c0/19a5d21f80cde11e7502d7380b17bb4634568dcd243eb72ce741277dd71aab2b20168e44060143b10bfa01f0b03a6b8a2628b3cf3e5d697b12cf7f78a16d469a
languageName: node
linkType: hard
"@expo/build-tools@npm:20.4.0, @expo/build-tools@workspace:packages/build-tools":
"@expo/build-tools@npm:20.5.1, @expo/build-tools@workspace:packages/build-tools":
version: 0.0.0-use.local
resolution: "@expo/build-tools@workspace:packages/build-tools"
dependencies:
"@expo/config": "npm:55.0.10"
"@expo/config-plugins": "npm:55.0.7"
"@expo/downloader": "npm:20.0.0"
"@expo/eas-build-job": "npm:20.1.0"
"@expo/eas-build-job": "npm:20.5.1"
"@expo/env": "npm:^0.4.0"
"@expo/logger": "npm:20.0.0"
"@expo/package-manager": "npm:1.9.10"
@@ -2871,7 +2871,7 @@ __metadata:
"@expo/repack-app": "npm:~0.6.1"
"@expo/results": "npm:^1.0.0"
"@expo/spawn-async": "npm:1.7.2"
"@expo/steps": "npm:20.1.0"
"@expo/steps": "npm:20.5.1"
"@expo/template-file": "npm:20.0.0"
"@expo/turtle-spawn": "npm:20.0.0"
"@expo/xcpretty": "npm:^4.3.1"
@@ -3113,7 +3113,7 @@ __metadata:
languageName: unknown
linkType: soft
"@expo/eas-build-job@npm:20.1.0, @expo/eas-build-job@workspace:packages/eas-build-job":
"@expo/eas-build-job@npm:20.5.1, @expo/eas-build-job@workspace:packages/eas-build-job":
version: 0.0.0-use.local
resolution: "@expo/eas-build-job@workspace:packages/eas-build-job"
dependencies:
@@ -3132,12 +3132,12 @@ __metadata:
languageName: unknown
linkType: soft
"@expo/eas-json@npm:20.1.0, @expo/eas-json@workspace:packages/eas-json":
"@expo/eas-json@npm:20.5.1, @expo/eas-json@workspace:packages/eas-json":
version: 0.0.0-use.local
resolution: "@expo/eas-json@workspace:packages/eas-json"
dependencies:
"@babel/code-frame": "npm:7.23.5"
"@expo/eas-build-job": "npm:20.1.0"
"@expo/eas-build-job": "npm:20.5.1"
"@tsconfig/node20": "npm:20.1.8"
"@types/babel__code-frame": "npm:7.0.3"
"@types/fs-extra": "npm:11.0.4"
@@ -3485,11 +3485,11 @@ __metadata:
languageName: node
linkType: hard
"@expo/steps@npm:20.1.0, @expo/steps@workspace:packages/steps":
"@expo/steps@npm:20.5.1, @expo/steps@workspace:packages/steps":
version: 0.0.0-use.local
resolution: "@expo/steps@workspace:packages/steps"
dependencies:
"@expo/eas-build-job": "npm:20.1.0"
"@expo/eas-build-job": "npm:20.5.1"
"@expo/logger": "npm:20.0.0"
"@expo/spawn-async": "npm:^1.7.2"
"@jest/globals": "npm:^29.7.0"
@@ -3558,16 +3558,16 @@ __metadata:
resolution: "@expo/worker@workspace:packages/worker"
dependencies:
"@babel/core": "npm:7.24.7"
"@expo/build-tools": "npm:20.4.0"
"@expo/build-tools": "npm:20.5.1"
"@expo/config-plugins": "npm:55.0.7"
"@expo/config-types": "npm:55.0.5"
"@expo/downloader": "npm:20.0.0"
"@expo/eas-build-job": "npm:20.1.0"
"@expo/eas-build-job": "npm:20.5.1"
"@expo/logger": "npm:20.0.0"
"@expo/results": "npm:1.0.0"
"@expo/rudder-sdk-node": "npm:1.1.1"
"@expo/spawn-async": "npm:1.7.2"
"@expo/steps": "npm:20.1.0"
"@expo/steps": "npm:20.5.1"
"@expo/template-file": "npm:20.0.0"
"@expo/turtle-spawn": "npm:20.0.0"
"@hapi/boom": "npm:10.0.1"
@@ -10487,7 +10487,7 @@ __metadata:
resolution: "create-eas-build-function@workspace:packages/create-eas-build-function"
dependencies:
"@expo/package-manager": "npm:1.9.10"
"@expo/steps": "npm:20.1.0"
"@expo/steps": "npm:20.5.1"
"@jest/globals": "npm:^29.7.0"
"@types/jest": "npm:^29.5.12"
"@types/node": "npm:20.14.2"
@@ -11100,8 +11100,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "eas-cli-local-build-plugin@workspace:packages/local-build-plugin"
dependencies:
"@expo/build-tools": "npm:20.4.0"
"@expo/eas-build-job": "npm:20.1.0"
"@expo/build-tools": "npm:20.5.1"
"@expo/eas-build-job": "npm:20.5.1"
"@expo/logger": "npm:20.0.0"
"@expo/spawn-async": "npm:^1.7.2"
"@expo/turtle-spawn": "npm:20.0.0"
@@ -11154,12 +11154,12 @@ __metadata:
version: 0.0.0-use.local
resolution: "eas-cli@workspace:packages/eas-cli"
dependencies:
"@expo/apple-utils": "npm:2.1.19"
"@expo/apple-utils": "npm:2.1.22"
"@expo/code-signing-certificates": "npm:0.0.5"
"@expo/config": "npm:55.0.10"
"@expo/config-plugins": "npm:55.0.7"
"@expo/eas-build-job": "npm:20.1.0"
"@expo/eas-json": "npm:20.1.0"
"@expo/eas-build-job": "npm:20.5.1"
"@expo/eas-json": "npm:20.5.1"
"@expo/env": "npm:^1.0.0"
"@expo/json-file": "npm:8.3.3"
"@expo/logger": "npm:20.0.0"
@@ -11174,7 +11174,7 @@ __metadata:
"@expo/results": "npm:1.0.0"
"@expo/rudder-sdk-node": "npm:1.1.1"
"@expo/spawn-async": "npm:1.7.2"
"@expo/steps": "npm:20.1.0"
"@expo/steps": "npm:20.5.1"
"@expo/timeago.js": "npm:1.0.0"
"@graphql-codegen/cli": "npm:5.0.0"
"@graphql-codegen/introspection": "npm:4.0.0"