Compare commits

...
Author SHA1 Message Date
Brent Vatne 39623f4694 Update CHANGELOG with PR number 2026-04-28 17:24:04 -07:00
Brent Vatne e70c52dc19 Fix interpolation dispatcher misclassifying multi-expression values
`interpolateJobContext` chooses between two branches based on whether the
value `startsWith('${{')` and `endsWith('}}')`. If both are true it
treats the value as a single expression, slices off the outer delimiters,
and hands the rest to jsep as one expression — preserving the result's
type for cases like `${{ inputs.flags }}` evaluating to an object.

The check does not verify those delimiters are a matched pair. A value
like `${{ a }}: ${{ b }}` also satisfies both conditions but is two
expressions joined by literal text. The dispatcher takes the wrong
branch and feeds jsep `a }}: ${{ b`, which produces the cryptic
`Unexpected "}" at character N` error.

Add a third condition: there must be no further `${{` after the opening
one. Multi-expression values then fall through to the existing
`replace(/\$\{\{(.+?)\}\}/g, ...)` branch which handles them correctly.
2026-04-28 17:23:23 -07:00
Szymon Dziedzic 1122a7f374 [eas-cli] prompt users to stop device run session when they are done by running eas simulator:stop command (#3633) 2026-04-28 20:24:20 +02:00
Stanisław Chmiela c06d18138c [worker] Set precompiled modules base URL (#3642)
## Summary

Sets `EXPO_PRECOMPILED_MODULES_BASE_URL` for iOS worker builds that opt into precompiled modules with `EAS_USE_PRECOMPILED_MODULES=1`.

When the CocoaPods cache is configured, the URL is routed through that cache using the same host-prefix style as other cached downloads. When the cache is not configured, it points directly to `https://storage.googleapis.com/eas-build-precompiled-modules/`.

Local builds are unchanged and do not receive this env var.

## Test Plan

- `yarn oxfmt packages/worker/src/env.ts packages/worker/src/__unit__/env.test.ts`
- `yarn workspace @expo/worker test:unit -- env.test.ts`
- `yarn workspace @expo/worker typecheck`
2026-04-28 19:33:42 +02:00
Szymon Dziedzic 3f4ff1dc3e [eas-cli] add eas simulator:stop command (#3626) 2026-04-27 14:11:13 +02:00
Mustafa Abban e852ab1cb7 [worker] - wrap error log fetch in try-catch to prevent unhandled rejections (#3631)
* [worker] - wrap error log fetch in try-catch to prevent unhandled rejections

* prevent real HTTP requests in integration tests
2026-04-24 12:28:11 -04:00
Mustafa Abban d941398ce6 [build-errors] - log all build errors with enriched metadata (#3612)
* enrich logs

* more metadata

* all error codes

* top level tags
2026-04-24 11:28:15 -04:00
Expo CI bae7684996 update CHANGELOG.md 2026-04-23 16:02:14 +00:00
Expo CI 714aec69c7 v18.8.1 2026-04-23 15:59:34 +00:00
Szymon Dziedzic bec6e670de [eas-cli] add eas simulator:start command (#3625) 2026-04-23 15:55:57 +00:00
27 changed files with 3225 additions and 120 deletions

No files matched your search

+4
View File
@@ -10,8 +10,12 @@ This is the log of notable changes to EAS CLI and related packages.
### 🐛 Bug fixes
- Fix EAS Workflows interpolation throwing `Unexpected "}" at character N` when a single value contains multiple `${{ ... }}` expressions (for example, `changelog: ${{ a }}: ${{ b }}`). ([#3643](https://github.com/expo/eas-cli/pull/3643) by [@brentvatne](https://github.com/brentvatne))
### 🧹 Chores
## [18.8.1](https://github.com/expo/eas-cli/releases/tag/v18.8.1) - 2026-04-23
## [18.8.0](https://github.com/expo/eas-cli/releases/tag/v18.8.0) - 2026-04-22
### 🎉 New features
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "18.8.0",
"version": "18.8.1",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@expo/build-tools",
"version": "18.8.0",
"version": "18.8.1",
"bugs": "https://github.com/expo/eas-cli/issues",
"license": "BUSL-1.1",
"author": "Expo <[email protected]>",
@@ -38,6 +38,7 @@ import { runGradleFunction } from './functions/runGradle';
import { createSaveBuildCacheFunction } from './functions/saveBuildCache';
import { createSaveCacheFunction } from './functions/saveCache';
import { createSendSlackMessageFunction } from './functions/sendSlackMessage';
import { createStartAgentDeviceRemoteSessionBuildFunction } from './functions/startAgentDeviceRemoteSession';
import { createStartAndroidEmulatorBuildFunction } from './functions/startAndroidEmulator';
import { createStartCuttlefishDeviceBuildFunction } from './functions/startCuttlefishDevice';
import { createStartIosSimulatorBuildFunction } from './functions/startIosSimulator';
@@ -77,6 +78,7 @@ export function getEasFunctions(ctx: CustomBuildContext): BuildFunction[] {
generateGymfileFromTemplateFunction(),
runFastlaneFunction(),
parseXcactivitylogFunction(),
createStartAgentDeviceRemoteSessionBuildFunction(),
createStartAndroidEmulatorBuildFunction(),
createStartCuttlefishDeviceBuildFunction(),
createStartIosSimulatorBuildFunction(),
@@ -0,0 +1,267 @@
import { bunyan } from '@expo/logger';
import { BuildFunction, BuildStepInput, BuildStepInputValueTypeName } from '@expo/steps';
import spawn from '@expo/turtle-spawn';
import childProcess from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { sleepAsync } from '../../utils/retry';
const AGENT_DEVICE_REPO_URL = 'https://github.com/callstackincubator/agent-device.git';
const SRC_DIR = '/tmp/agent-device-src';
const RUN_DIR = '/tmp/agent-device';
const DAEMON_LOG = path.join(RUN_DIR, 'daemon.log');
const TUNNEL_LOG = path.join(RUN_DIR, 'cloudflared.log');
const DAEMON_JSON_PATH = path.join(os.homedir(), '.agent-device', 'daemon.json');
const XCODE_DEVELOPER_DIR = '/Applications/Xcode.app/Contents/Developer';
const STARTUP_TIMEOUT_MS = 60_000;
export function createStartAgentDeviceRemoteSessionBuildFunction(): BuildFunction {
return new BuildFunction({
namespace: 'eas',
id: 'start_agent_device_remote_session',
name: 'Start agent device remote session',
__metricsId: 'eas/start_agent_device_remote_session',
inputProviders: [
BuildStepInput.createProvider({
id: 'package_version',
required: false,
allowedValueTypeName: BuildStepInputValueTypeName.STRING,
}),
],
fn: async ({ logger }, { inputs, env }) => {
const packageVersion = inputs.package_version.value as string | undefined;
logger.info(`Starting agent-device remote session (version: ${packageVersion ?? 'latest'}).`);
logger.info(`Preparing runtime directory at ${RUN_DIR}.`);
await fs.promises.mkdir(RUN_DIR, { recursive: true });
logger.info(`Selecting Xcode developer directory: ${XCODE_DEVELOPER_DIR}.`);
await spawn('sudo', ['xcode-select', '-s', XCODE_DEVELOPER_DIR], { env, logger });
logger.info('Ensuring cloudflared is installed.');
await ensureCloudflaredInstalledAsync({ env, logger });
logger.info('Ensuring bun is installed.');
await ensureBunInstalledAsync({ env, logger });
logger.info(
packageVersion
? `Cloning agent-device @ v${packageVersion} into ${SRC_DIR}.`
: `Cloning agent-device (latest) into ${SRC_DIR}.`
);
await cloneAgentDeviceAsync({ packageVersion, env, logger });
logger.info('Installing agent-device dependencies.');
await spawn('bun', ['install', '--production'], {
cwd: SRC_DIR,
env,
logger,
});
logger.info(`Launching agent-device daemon (log file: ${DAEMON_LOG}).`);
await spawnDetachedAsync({
command: 'bun run src/daemon.ts',
cwd: SRC_DIR,
logFile: DAEMON_LOG,
env: { ...env, AGENT_DEVICE_DAEMON_SERVER_MODE: 'http' },
logger,
});
logger.info(`Waiting for daemon credentials at ${DAEMON_JSON_PATH}.`);
await waitForFileAsync({
filePath: DAEMON_JSON_PATH,
timeoutMs: STARTUP_TIMEOUT_MS,
description: 'agent-device daemon',
});
const { port: daemonPort, token: daemonToken } = readDaemonInfo(DAEMON_JSON_PATH);
logger.info(`Daemon is listening on port ${daemonPort}; loaded auth token.`);
logger.info(
`Starting cloudflared tunnel to http://localhost:${daemonPort} (log file: ${TUNNEL_LOG}).`
);
await spawnDetachedAsync({
command: `cloudflared tunnel --url "http://localhost:${daemonPort}"`,
logFile: TUNNEL_LOG,
env,
logger,
});
logger.info('Waiting for a public tunnel URL.');
const tunnelUrl = await waitForMatchInLogAsync({
logFile: TUNNEL_LOG,
pattern: /https:\/\/[a-z0-9-]+\.trycloudflare\.com/,
timeoutMs: STARTUP_TIMEOUT_MS,
description: 'cloudflared tunnel',
});
logger.info(`Tunnel is ready at ${tunnelUrl}.`);
logger.info('Emitting agent-device credentials for the CLI to pick up:');
logger.info(`export AGENT_DEVICE_DAEMON_BASE_URL="${tunnelUrl}"`);
logger.info(`export AGENT_DEVICE_DAEMON_AUTH_TOKEN="${daemonToken}"`);
logger.info('Remote session is live. Keeping the job alive until the session is stopped.');
// Keep the turtle job alive so the daemon and tunnel stay reachable
// until stopDeviceRunSession cancels the run.
await new Promise<never>(() => {});
},
});
}
async function ensureCloudflaredInstalledAsync({
env,
logger,
}: {
env: NodeJS.ProcessEnv;
logger: bunyan;
}): Promise<void> {
await ensureBrewPackageInstalledAsync({ name: 'cloudflared', env, logger });
}
async function ensureBunInstalledAsync({
env,
logger,
}: {
env: NodeJS.ProcessEnv;
logger: bunyan;
}): Promise<void> {
await ensureBrewPackageInstalledAsync({ name: 'bun', env, logger });
}
async function ensureBrewPackageInstalledAsync({
name,
env,
logger,
}: {
name: string;
env: NodeJS.ProcessEnv;
logger: bunyan;
}): Promise<void> {
await spawn(
'bash',
['-c', `command -v ${name} >/dev/null 2>&1 || HOMEBREW_NO_AUTO_UPDATE=1 brew install ${name}`],
{ env, logger }
);
}
async function cloneAgentDeviceAsync({
packageVersion,
env,
logger,
}: {
packageVersion: string | undefined;
env: NodeJS.ProcessEnv;
logger: bunyan;
}): Promise<void> {
const branchArgs = packageVersion ? ['--branch', `v${packageVersion}`] : [];
await spawn('git', ['clone', '--depth', '1', ...branchArgs, AGENT_DEVICE_REPO_URL, SRC_DIR], {
env,
logger,
});
}
async function spawnDetachedAsync({
command,
cwd,
logFile,
env,
logger,
}: {
command: string;
cwd?: string;
logFile: string;
env: NodeJS.ProcessEnv;
logger: bunyan;
}): Promise<void> {
// Launch the process fully detached so this function returns immediately and
// the grandchild survives the step. Stdio goes to a log file so the daemon
// output can be polled, and we unref so Node doesn't wait on it.
const fd = fs.openSync(logFile, 'a');
try {
const child = childProcess.spawn('bash', ['-c', command], {
cwd,
env,
detached: true,
stdio: ['ignore', fd, fd],
});
if (!child.pid) {
throw new Error(`Failed to spawn detached process: ${command}`);
}
child.unref();
logger.info(`Started detached process (pid ${child.pid}).`);
} finally {
fs.closeSync(fd);
}
}
async function waitForMatchInLogAsync({
logFile,
pattern,
timeoutMs,
description,
}: {
logFile: string;
pattern: RegExp;
timeoutMs: number;
description: string;
}): Promise<string> {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const content = await readFileOrEmptyAsync(logFile);
const match = pattern.exec(content);
if (match) {
return match[1] ?? match[0];
}
await sleepAsync(1_000);
}
const tail = await readFileOrEmptyAsync(logFile);
throw new Error(
`Timed out waiting for ${description} to start. Last log contents:\n${tail || '<empty>'}`
);
}
async function waitForFileAsync({
filePath,
timeoutMs,
description,
}: {
filePath: string;
timeoutMs: number;
description: string;
}): Promise<void> {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
try {
await fs.promises.access(filePath);
return;
} catch {
// not yet; keep polling
}
await sleepAsync(1_000);
}
throw new Error(`Timed out waiting for ${description} to write ${filePath}.`);
}
async function readFileOrEmptyAsync(filePath: string): Promise<string> {
try {
return await fs.promises.readFile(filePath, 'utf8');
} catch {
return '';
}
}
function readDaemonInfo(filePath: string): { port: number; token: string } {
const raw = fs.readFileSync(filePath, 'utf8');
const parsed = JSON.parse(raw) as unknown;
if (
!parsed ||
typeof parsed !== 'object' ||
typeof (parsed as { httpPort: unknown }).httpPort !== 'number' ||
typeof (parsed as { token: unknown }).token !== 'string'
) {
throw new Error(`Expected ${filePath} to contain { "httpPort": <number>, "token": "..." }.`);
}
const { httpPort, token } = parsed as { httpPort: number; token: string };
return { port: httpPort, token };
}
+90 -90
View File
@@ -180,7 +180,7 @@ ALIASES
$ eas login
```
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -197,7 +197,7 @@ ALIASES
$ eas logout
```
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:usage [ACCOUNT_NAME]`
@@ -219,7 +219,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/account/usage.ts)_
## `eas account:view`
@@ -236,7 +236,7 @@ ALIASES
$ eas whoami
```
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -250,7 +250,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v18.8.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v18.8.1/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -302,7 +302,7 @@ DESCRIPTION
create a branch
```
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -323,7 +323,7 @@ DESCRIPTION
delete a branch
```
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -343,7 +343,7 @@ DESCRIPTION
list all branches
```
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -363,7 +363,7 @@ DESCRIPTION
rename a branch
```
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -386,7 +386,7 @@ DESCRIPTION
view a branch
```
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -424,7 +424,7 @@ DESCRIPTION
start a build
```
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -444,7 +444,7 @@ DESCRIPTION
cancel a build
```
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -462,7 +462,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
@@ -482,7 +482,7 @@ DESCRIPTION
delete a build
```
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/delete.ts)_
## `eas build:dev`
@@ -504,7 +504,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/dev.ts)_
## `eas build:download`
@@ -525,7 +525,7 @@ DESCRIPTION
download simulator/emulator builds for a given fingerprint hash
```
_See code: [packages/eas-cli/src/commands/build/download.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/download.ts)_
## `eas build:inspect`
@@ -563,7 +563,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -603,7 +603,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -633,7 +633,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -659,7 +659,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -711,7 +711,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -729,7 +729,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -747,7 +747,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -764,7 +764,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -785,7 +785,7 @@ DESCRIPTION
create a channel
```
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:delete [NAME]`
@@ -806,7 +806,7 @@ DESCRIPTION
Delete a channel
```
_See code: [packages/eas-cli/src/commands/channel/delete.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/delete.ts)_
## `eas channel:edit [NAME]`
@@ -828,7 +828,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:insights`
@@ -852,7 +852,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/insights.ts)_
## `eas channel:list`
@@ -872,7 +872,7 @@ DESCRIPTION
list all channels
```
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:pause [NAME]`
@@ -894,7 +894,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/pause.ts)_
## `eas channel:resume [NAME]`
@@ -916,7 +916,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/resume.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -951,7 +951,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -974,7 +974,7 @@ DESCRIPTION
view a channel
```
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -995,7 +995,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/v18.8.0/packages/eas-cli/src/commands/config.ts)_
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v18.8.1/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -1012,7 +1012,7 @@ DESCRIPTION
manage credentials
```
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/credentials/index.ts)_
## `eas credentials:configure-build`
@@ -1030,7 +1030,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/credentials/configure-build.ts)_
## `eas deploy [options]`
@@ -1059,7 +1059,7 @@ ALIASES
$ eas worker:deploy
```
_See code: [packages/eas-cli/src/commands/deploy/index.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/deploy/index.ts)_
## `eas deploy:alias`
@@ -1084,7 +1084,7 @@ ALIASES
$ eas deploy:promote
```
_See code: [packages/eas-cli/src/commands/deploy/alias/index.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/deploy/alias/index.ts)_
## `eas deploy:alias:delete [ALIAS_NAME]`
@@ -1105,7 +1105,7 @@ ALIASES
$ eas worker:alias:delete
```
_See code: [packages/eas-cli/src/commands/deploy/alias/delete.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/deploy/alias/delete.ts)_
## `eas deploy:delete [DEPLOYMENT_ID]`
@@ -1126,7 +1126,7 @@ ALIASES
$ eas worker:delete
```
_See code: [packages/eas-cli/src/commands/deploy/delete.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/deploy/delete.ts)_
## `eas deploy:promote`
@@ -1163,7 +1163,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -1183,7 +1183,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -1204,7 +1204,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -1225,7 +1225,7 @@ DESCRIPTION
rename a registered device
```
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -1239,7 +1239,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -1253,7 +1253,7 @@ DESCRIPTION
display environment info
```
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v18.8.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v18.8.1/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas env:create [ENVIRONMENT]`
@@ -1285,7 +1285,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/create.ts)_
## `eas env:delete [ENVIRONMENT]`
@@ -1311,7 +1311,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/delete.ts)_
## `eas env:exec ENVIRONMENT BASH_COMMAND`
@@ -1333,7 +1333,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/exec.ts)_
## `eas env:get [ENVIRONMENT]`
@@ -1361,7 +1361,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/get.ts)_
## `eas env:list [ENVIRONMENT]`
@@ -1389,7 +1389,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/list.ts)_
## `eas env:pull [ENVIRONMENT]`
@@ -1412,7 +1412,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/pull.ts)_
## `eas env:push [ENVIRONMENT]`
@@ -1434,7 +1434,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/push.ts)_
## `eas env:update [ENVIRONMENT]`
@@ -1468,7 +1468,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/env/update.ts)_
## `eas fingerprint:compare [HASH1] [HASH2]`
@@ -1512,7 +1512,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/fingerprint/compare.ts)_
## `eas fingerprint:generate`
@@ -1543,7 +1543,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/fingerprint/generate.ts)_
## `eas help [COMMAND]`
@@ -1652,7 +1652,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1670,7 +1670,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1688,7 +1688,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas new [PATH]`
@@ -1740,7 +1740,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/v18.8.0/packages/eas-cli/src/commands/open.ts)_
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v18.8.1/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1754,7 +1754,7 @@ DESCRIPTION
information about the current project
```
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1777,7 +1777,7 @@ ALIASES
$ eas init
```
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/project/init.ts)_
## `eas project:new [PATH]`
@@ -1801,7 +1801,7 @@ ALIASES
$ eas new
```
_See code: [packages/eas-cli/src/commands/project/new.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/project/new.ts)_
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1819,7 +1819,7 @@ ALIASES
$ eas onboarding
```
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/project/onboarding.ts)_
## `eas submit`
@@ -1852,7 +1852,7 @@ ALIASES
$ eas build:submit
```
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v18.8.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v18.8.1/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1895,7 +1895,7 @@ DESCRIPTION
publish an update group
```
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1916,7 +1916,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1937,7 +1937,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:edit [GROUPID]`
@@ -1962,7 +1962,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/edit.ts)_
## `eas update:insights GROUPID`
@@ -1989,7 +1989,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/insights.ts)_
## `eas update:list`
@@ -2016,7 +2016,7 @@ DESCRIPTION
view the recent updates
```
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -2054,7 +2054,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:revert-update-rollout`
@@ -2082,7 +2082,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/revert-update-rollout.ts)_
## `eas update:roll-back-to-embedded`
@@ -2112,7 +2112,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -2133,7 +2133,7 @@ DESCRIPTION
instead execute "eas update:republish" or "eas update:roll-back-to-embedded".
```
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -2157,7 +2157,7 @@ DESCRIPTION
update group details
```
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/update/view.ts)_
## `eas upload`
@@ -2178,7 +2178,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/v18.8.0/packages/eas-cli/src/commands/upload.ts)_
_See code: [packages/eas-cli/src/commands/upload.ts](https://github.com/expo/eas-cli/blob/v18.8.1/packages/eas-cli/src/commands/upload.ts)_
## `eas webhook:create`
@@ -2200,7 +2200,7 @@ DESCRIPTION
create a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -2220,7 +2220,7 @@ DESCRIPTION
delete a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -2239,7 +2239,7 @@ DESCRIPTION
list webhooks
```
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -2262,7 +2262,7 @@ DESCRIPTION
update a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -2279,7 +2279,7 @@ DESCRIPTION
view a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
@@ -2400,7 +2400,7 @@ DESCRIPTION
to cancel.
```
_See code: [packages/eas-cli/src/commands/workflow/cancel.ts](https://github.com/expo/eas-cli/blob/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/cancel.ts)_
## `eas workflow:create [NAME]`
@@ -2420,7 +2420,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/create.ts)_
## `eas workflow:logs [ID]`
@@ -2444,7 +2444,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/logs.ts)_
## `eas workflow:run FILE`
@@ -2484,7 +2484,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/run.ts)_
## `eas workflow:runs`
@@ -2506,7 +2506,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/runs.ts)_
## `eas workflow:status [WORKFLOW_RUN_ID]`
@@ -2534,7 +2534,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/status.ts)_
## `eas workflow:validate PATH`
@@ -2554,7 +2554,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/validate.ts)_
## `eas workflow:view [ID]`
@@ -2576,5 +2576,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/v18.8.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/v18.8.1/packages/eas-cli/src/commands/workflow/view.ts)_
<!-- commandsstop -->
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eas-cli",
"version": "18.8.0",
"version": "18.8.1",
"description": "EAS command line tool",
"keywords": [
"cli",
+18
View File
@@ -64,6 +64,24 @@ export function getWorkflowRunUrl(
).toString();
}
/**
* @deprecated Links to the raw job-run page; prefer a higher-level URL (e.g. the workflow run
* or the feature-specific dashboard) that gives users more context. Use this only for internal
* tooling where no richer URL exists.
*/
export function getBareJobRunUrl(
accountName: string,
projectName: string,
jobRunId: string
): string {
return new URL(
`/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent(
projectName
)}/job-runs/${encodeURIComponent(jobRunId)}`,
getExpoWebsiteBaseUrl()
).toString();
}
export function getProjectGitHubSettingsUrl(accountName: string, projectName: string): string {
return new URL(
`/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent(
@@ -0,0 +1,256 @@
import { Flags } from '@oclif/core';
import { getBareJobRunUrl } from '../../build/utils/url';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
import {
AppPlatform,
DeviceRunSessionStatus,
DeviceRunSessionType,
JobRunStatus,
} from '../../graphql/generated';
import { DeviceRunSessionMutation } from '../../graphql/mutations/DeviceRunSessionMutation';
import { DeviceRunSessionQuery } from '../../graphql/queries/DeviceRunSessionQuery';
import Log, { link } from '../../log';
import { ora } from '../../ora';
import { sleepAsync } from '../../utils/promise';
import nullthrows from 'nullthrows';
const POLL_INTERVAL_MS = 5_000; // 5 seconds
const POLL_TIMEOUT_MS = 15 * 60 * 1_000; // 15 minutes
// Mapping enum → CLI flag value. Declared as Record<DeviceRunSessionType, string>
// so adding a new enum value in codegen fails the build until it is wired up here.
const DEVICE_RUN_SESSION_TYPE_FLAG_VALUES: Record<DeviceRunSessionType, string> = {
[DeviceRunSessionType.AgentDevice]: 'agent-device',
};
const DEVICE_RUN_SESSION_TYPE_BY_FLAG_VALUE = Object.fromEntries(
(Object.entries(DEVICE_RUN_SESSION_TYPE_FLAG_VALUES) as [DeviceRunSessionType, string][]).map(
([type, value]) => [value, type]
)
) as Record<string, DeviceRunSessionType>;
type ReadinessResult = { ready: true; message: string } | { ready: false };
type ReadinessChecker = (logMessages: readonly string[]) => ReadinessResult;
export default class SimulatorStart extends EasCommand {
static override hidden = true;
static override description =
'[EXPERIMENTAL] start a remote simulator session on EAS and get the credentials to connect to it with the CLI tool of your choice';
static override flags = {
platform: Flags.option({
description: 'Device platform',
options: ['android', 'ios'] as const,
required: true,
})(),
type: Flags.option({
description: 'Type of device run session to create',
options: Object.values(DEVICE_RUN_SESSION_TYPE_FLAG_VALUES),
default: DEVICE_RUN_SESSION_TYPE_FLAG_VALUES[DeviceRunSessionType.AgentDevice],
})(),
'package-version': Flags.string({
description:
'Version of the package backing the device run session (e.g. "0.1.3-alpha.3"). Defaults to "latest" when omitted.',
}),
...EASNonInteractiveFlag,
};
static override contextDefinition = {
...this.ContextOptions.ProjectId,
...this.ContextOptions.LoggedIn,
};
async runAsync(): Promise<void> {
const { flags } = await this.parse(SimulatorStart);
const {
projectId,
loggedIn: { graphqlClient },
} = await this.getContextAsync(SimulatorStart, {
nonInteractive: flags['non-interactive'],
});
const platform = flags.platform === 'android' ? AppPlatform.Android : AppPlatform.Ios;
const createSpinner = ora('🚀 Creating device run session').start();
let deviceRunSessionId: string;
try {
const session = await DeviceRunSessionMutation.createDeviceRunSessionAsync(graphqlClient, {
appId: projectId,
platform,
type: DEVICE_RUN_SESSION_TYPE_BY_FLAG_VALUE[flags.type],
packageVersion: flags['package-version'],
});
deviceRunSessionId = session.id;
const jobRunId = nullthrows(session.turtleJobRun?.id, 'Expected device run session to start');
const jobRunUrl = getBareJobRunUrl(session.app.ownerAccount.name, session.app.slug, jobRunId);
createSpinner.succeed(
`Device run session created (id: ${deviceRunSessionId}) ${link(jobRunUrl)}`
);
} catch (err) {
createSpinner.fail('Failed to create device run session');
throw err;
}
const checkReadiness = getReadinessCheckerForType(flags.type);
const pollSpinner = ora(`⏳ Waiting for ${flags.type} daemon to start`).start();
const deadline = Date.now() + POLL_TIMEOUT_MS;
let result: ReadinessResult = { ready: false };
try {
while (Date.now() < deadline) {
const session = await DeviceRunSessionQuery.byIdAsync(graphqlClient, deviceRunSessionId);
if (
session.status === DeviceRunSessionStatus.Errored ||
session.status === DeviceRunSessionStatus.Stopped
) {
throw new Error(
`Device run session ${deviceRunSessionId} ${session.status.toLowerCase()} before the ${flags.type} daemon was ready.`
);
}
const jobRunStatus = session.turtleJobRun?.status;
if (
jobRunStatus === JobRunStatus.Errored ||
jobRunStatus === JobRunStatus.Canceled ||
jobRunStatus === JobRunStatus.Finished
) {
throw new Error(
`Turtle job run for device run session ${deviceRunSessionId} ${jobRunStatus.toLowerCase()} before the ${flags.type} daemon was ready.`
);
}
const logMessages = await fetchLogMessagesAsync(session.turtleJobRun?.logFileUrls ?? []);
result = checkReadiness(logMessages);
if (result.ready) {
pollSpinner.succeed(`🎉 ${flags.type} daemon is ready`);
break;
}
await sleepAsync(POLL_INTERVAL_MS);
}
} catch (err) {
pollSpinner.fail(`Failed while polling for ${flags.type} daemon logs`);
throw err;
}
if (!result.ready) {
pollSpinner.fail(`Timed out waiting for ${flags.type} daemon to start`);
throw new Error(
`Timed out after ${Math.round(POLL_TIMEOUT_MS / 1000)}s waiting for ${flags.type} daemon to start.`
);
}
Log.newLine();
Log.log(`🔑 Run the following in your shell to attach to ${flags.type}:`);
Log.newLine();
Log.log(result.message);
Log.newLine();
Log.log(
`When you are done, stop the session with: eas simulator:stop --id ${deviceRunSessionId}`
);
}
}
function getReadinessCheckerForType(type: string): ReadinessChecker {
switch (type) {
case DEVICE_RUN_SESSION_TYPE_FLAG_VALUES[DeviceRunSessionType.AgentDevice]:
return checkAgentDeviceReadiness;
default:
throw new Error(`Unsupported device run session type: ${type}`);
}
}
const AGENT_DEVICE_BASE_URL_ENV_VAR = 'AGENT_DEVICE_DAEMON_BASE_URL';
const AGENT_DEVICE_AUTH_TOKEN_ENV_VAR = 'AGENT_DEVICE_DAEMON_AUTH_TOKEN';
function checkAgentDeviceReadiness(logMessages: readonly string[]): ReadinessResult {
let baseUrl: string | undefined;
let authToken: string | undefined;
for (const msg of logMessages) {
baseUrl = baseUrl ?? extractExportedEnvValue(msg, AGENT_DEVICE_BASE_URL_ENV_VAR);
authToken = authToken ?? extractExportedEnvValue(msg, AGENT_DEVICE_AUTH_TOKEN_ENV_VAR);
if (baseUrl && authToken) {
break;
}
}
if (baseUrl && authToken) {
return {
ready: true,
message: [
`export ${AGENT_DEVICE_BASE_URL_ENV_VAR}='${baseUrl}'`,
`export ${AGENT_DEVICE_AUTH_TOKEN_ENV_VAR}='${authToken}'`,
].join('\n'),
};
}
return { ready: false };
}
async function fetchLogMessagesAsync(logUrls: readonly string[]): Promise<string[]> {
const messages: string[] = [];
for (const url of logUrls) {
const text = await fetchLogTextAsync(url);
if (!text) {
continue;
}
for (const line of text.split('\n')) {
if (!line.trim()) {
continue;
}
messages.push(extractLogMessage(line));
}
}
return messages;
}
async function fetchLogTextAsync(url: string): Promise<string | undefined> {
try {
const response = await fetch(url);
if (!response.ok) {
return undefined;
}
return await response.text();
} catch {
return undefined;
}
}
function extractLogMessage(line: string): string {
// Turtle job run logs are JSONL (bunyan-shaped), e.g.
// {"msg":"export FOO=\"bar\"","time":"...","logId":"..."}
// Fall back to the raw line if it's not JSON or doesn't have a string msg.
const trimmed = line.trim();
if (!trimmed.startsWith('{')) {
return line;
}
try {
const parsed = JSON.parse(trimmed) as unknown;
if (parsed && typeof parsed === 'object' && 'msg' in parsed) {
const msg = (parsed as { msg: unknown }).msg;
if (typeof msg === 'string') {
return msg;
}
}
} catch {
// not JSON, fall through
}
return line;
}
function extractExportedEnvValue(text: string, varName: string): string | undefined {
// Matches: export NAME=value | export NAME="value" | export NAME='value'
const pattern = new RegExp(`export\\s+${escapeRegExp(varName)}=(?:"([^"]*)"|'([^']*)'|(\\S+))`);
const match = pattern.exec(text);
if (!match) {
return undefined;
}
return match[1] ?? match[2] ?? match[3];
}
function escapeRegExp(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
@@ -0,0 +1,46 @@
import { Flags } from '@oclif/core';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
import { DeviceRunSessionMutation } from '../../graphql/mutations/DeviceRunSessionMutation';
import { ora } from '../../ora';
export default class SimulatorStop extends EasCommand {
static override hidden = true;
static override description =
'[EXPERIMENTAL] stop a remote simulator session on EAS by its device run session ID';
static override flags = {
id: Flags.string({
description: 'Device run session ID',
required: true,
}),
...EASNonInteractiveFlag,
};
static override contextDefinition = {
...this.ContextOptions.LoggedIn,
};
async runAsync(): Promise<void> {
const { flags } = await this.parse(SimulatorStop);
const {
loggedIn: { graphqlClient },
} = await this.getContextAsync(SimulatorStop, {
nonInteractive: flags['non-interactive'],
});
const stopSpinner = ora(`🛑 Stopping device run session ${flags.id}`).start();
try {
const session = await DeviceRunSessionMutation.stopDeviceRunSessionAsync(
graphqlClient,
flags.id
);
stopSpinner.succeed(`🎉 Device run session ${session.id} is ${session.status.toLowerCase()}`);
} catch (err) {
stopSpinner.fail(`Failed to stop device run session ${flags.id}`);
throw err;
}
}
}
+257
View File
@@ -1399,6 +1399,7 @@ export type App = Project & {
*/
buildsReleaseChannels: Array<Scalars['String']['output']>;
channelsPaginated: AppChannelsConnection;
convexProject?: Maybe<ConvexProject>;
deployment?: Maybe<Deployment>;
/** Deployments associated with this app */
deployments: DeploymentsConnection;
@@ -2086,6 +2087,9 @@ export type AppNotificationPreferenceInput = {
export type AppObserve = {
__typename?: 'AppObserve';
appVersions: Array<AppObserveAppVersion>;
customEventCounts: AppObserveCustomEventCounts;
customEventList: AppObserveCustomEventListConnection;
customEventNames: AppObserveCustomEventNames;
environments: Array<Scalars['String']['output']>;
events: AppObserveEventsConnection;
timeSeries: AppObserveTimeSeries;
@@ -2098,6 +2102,28 @@ export type AppObserveAppVersionsArgs = {
};
export type AppObserveCustomEventCountsArgs = {
input: AppObserveCustomEventCountsInput;
};
export type AppObserveCustomEventListArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
filter?: InputMaybe<AppObserveCustomEventListFilter>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
};
export type AppObserveCustomEventNamesArgs = {
endTime: Scalars['DateTime']['input'];
environment?: InputMaybe<Scalars['String']['input']>;
platform?: InputMaybe<AppObservePlatform>;
startTime: Scalars['DateTime']['input'];
};
export type AppObserveEnvironmentsArgs = {
endTime?: InputMaybe<Scalars['DateTime']['input']>;
platform?: InputMaybe<AppObservePlatform>;
@@ -2163,6 +2189,96 @@ export type AppObserveAppVersionMetric = {
statistics: AppObserveVersionMarkerStatistics;
};
export type AppObserveCustomEvent = {
__typename?: 'AppObserveCustomEvent';
appBuildNumber: Scalars['String']['output'];
appEasBuildId?: Maybe<Scalars['String']['output']>;
appUpdateId?: Maybe<Scalars['String']['output']>;
appVersion: Scalars['String']['output'];
countryCode?: Maybe<Scalars['String']['output']>;
deviceModel: Scalars['String']['output'];
deviceOs: Scalars['String']['output'];
deviceOsVersion: Scalars['String']['output'];
easClientId: Scalars['String']['output'];
environment?: Maybe<Scalars['String']['output']>;
eventName: Scalars['String']['output'];
id: Scalars['ID']['output'];
properties: Array<AppObserveEventProperty>;
sessionId?: Maybe<Scalars['String']['output']>;
severityNumber?: Maybe<Scalars['Int']['output']>;
severityText?: Maybe<Scalars['String']['output']>;
timestamp: Scalars['DateTime']['output'];
};
export type AppObserveCustomEventCountBucket = {
__typename?: 'AppObserveCustomEventCountBucket';
bucket: Scalars['DateTime']['output'];
count: Scalars['Int']['output'];
};
export type AppObserveCustomEventCounts = {
__typename?: 'AppObserveCustomEventCounts';
buckets: Array<AppObserveCustomEventCountBucket>;
totalCount: Scalars['Int']['output'];
};
export type AppObserveCustomEventCountsInput = {
appBuildNumber?: InputMaybe<Scalars['String']['input']>;
appEasBuildId?: InputMaybe<Scalars['String']['input']>;
appUpdateId?: InputMaybe<Scalars['String']['input']>;
appVersion?: InputMaybe<Scalars['String']['input']>;
bucketIntervalMinutes?: InputMaybe<Scalars['Int']['input']>;
endTime: Scalars['DateTime']['input'];
environment?: InputMaybe<Scalars['String']['input']>;
eventName: Scalars['String']['input'];
platform: AppObservePlatform;
startTime: Scalars['DateTime']['input'];
};
export type AppObserveCustomEventEdge = {
__typename?: 'AppObserveCustomEventEdge';
cursor: Scalars['String']['output'];
node: AppObserveCustomEvent;
};
export type AppObserveCustomEventListConnection = {
__typename?: 'AppObserveCustomEventListConnection';
edges: Array<AppObserveCustomEventEdge>;
pageInfo: PageInfo;
};
export type AppObserveCustomEventListFilter = {
appBuildNumber?: InputMaybe<Scalars['String']['input']>;
appEasBuildId?: InputMaybe<Scalars['String']['input']>;
appUpdateId?: InputMaybe<Scalars['String']['input']>;
appVersion?: InputMaybe<Scalars['String']['input']>;
easClientId?: InputMaybe<Scalars['String']['input']>;
endTime?: InputMaybe<Scalars['DateTime']['input']>;
environment?: InputMaybe<Scalars['String']['input']>;
eventName?: InputMaybe<Scalars['String']['input']>;
platform?: InputMaybe<AppObservePlatform>;
propertyFilters?: InputMaybe<Array<AppObserveCustomEventPropertyFilter>>;
sessionId?: InputMaybe<Scalars['String']['input']>;
startTime?: InputMaybe<Scalars['DateTime']['input']>;
};
export type AppObserveCustomEventName = {
__typename?: 'AppObserveCustomEventName';
count: Scalars['Int']['output'];
eventName: Scalars['String']['output'];
};
export type AppObserveCustomEventNames = {
__typename?: 'AppObserveCustomEventNames';
isTruncated: Scalars['Boolean']['output'];
names: Array<AppObserveCustomEventName>;
};
export type AppObserveCustomEventPropertyFilter = {
key: Scalars['String']['input'];
value: Scalars['String']['input'];
};
export type AppObserveEvent = {
__typename?: 'AppObserveEvent';
appBuildNumber: Scalars['String']['output'];
@@ -2202,6 +2318,13 @@ export type AppObserveEventEdge = {
node: AppObserveEvent;
};
export type AppObserveEventProperty = {
__typename?: 'AppObserveEventProperty';
key: Scalars['String']['output'];
type: AppObservePropertyType;
value: Scalars['String']['output'];
};
export type AppObserveEventsConnection = {
__typename?: 'AppObserveEventsConnection';
edges: Array<AppObserveEventEdge>;
@@ -2242,6 +2365,13 @@ export enum AppObservePlatform {
Ios = 'IOS'
}
export enum AppObservePropertyType {
Boolean = 'BOOLEAN',
Json = 'JSON',
Number = 'NUMBER',
String = 'STRING'
}
export type AppObserveReleasesInput = {
endTime: Scalars['DateTime']['input'];
environment?: InputMaybe<Scalars['String']['input']>;
@@ -2850,6 +2980,23 @@ export type AppleDeviceRegistrationRequestMutationCreateAppleDeviceRegistrationR
appleTeamId: Scalars['ID']['input'];
};
/** Publicly visible data for an AppleDeviceRegistrationRequest. */
export type AppleDeviceRegistrationRequestPublicData = {
__typename?: 'AppleDeviceRegistrationRequestPublicData';
id: Scalars['ID']['output'];
};
export type AppleDeviceRegistrationRequestPublicDataQuery = {
__typename?: 'AppleDeviceRegistrationRequestPublicDataQuery';
/** Get AppleDeviceRegistrationRequest public data by ID */
byId?: Maybe<AppleDeviceRegistrationRequestPublicData>;
};
export type AppleDeviceRegistrationRequestPublicDataQueryByIdArgs = {
id: Scalars['ID']['input'];
};
export type AppleDeviceRegistrationRequestQuery = {
__typename?: 'AppleDeviceRegistrationRequestQuery';
byId: AppleDeviceRegistrationRequest;
@@ -4072,6 +4219,18 @@ export type ConvexIntegrationQuery = {
clientIdentifier: Scalars['String']['output'];
};
export type ConvexProject = {
__typename?: 'ConvexProject';
app: App;
convexProjectIdentifier: Scalars['String']['output'];
convexProjectName: Scalars['String']['output'];
convexProjectSlug: Scalars['String']['output'];
convexTeamConnection: ConvexTeamConnection;
createdAt: Scalars['DateTime']['output'];
id: Scalars['ID']['output'];
updatedAt: Scalars['DateTime']['output'];
};
export type ConvexTeamConnection = {
__typename?: 'ConvexTeamConnection';
account: Account;
@@ -4173,6 +4332,17 @@ export type CreateConvexTeamConnectionInput = {
deploymentRegion: Scalars['String']['input'];
};
export type CreateDeviceRunSessionInput = {
appId: Scalars['ID']['input'];
/**
* The version of the package backing the device run session (e.g. "0.1.3-alpha.3").
* If omitted, consumers treat the session as pinned to "latest".
*/
packageVersion?: InputMaybe<Scalars['String']['input']>;
platform: AppPlatform;
type: DeviceRunSessionType;
};
export type CreateEchoChatInput = {
agentMetadata?: InputMaybe<Scalars['JSONObject']['input']>;
agentType?: InputMaybe<EchoAgentType>;
@@ -4770,6 +4940,65 @@ export type DeploymentsMutationDeleteWorkerDeploymentByIdentifierArgs = {
deploymentIdentifier: Scalars['ID']['input'];
};
export type DeviceRunSession = {
__typename?: 'DeviceRunSession';
app: App;
createdAt: Scalars['DateTime']['output'];
finishedAt?: Maybe<Scalars['DateTime']['output']>;
id: Scalars['ID']['output'];
initiatingActor?: Maybe<Actor>;
/**
* The version of the package backing the device run session. Null means the session is
* pinned to "latest" at the consumer side.
*/
packageVersion?: Maybe<Scalars['String']['output']>;
platform: AppPlatform;
startedAt?: Maybe<Scalars['DateTime']['output']>;
status: DeviceRunSessionStatus;
turtleJobRun?: Maybe<JobRun>;
type: DeviceRunSessionType;
updatedAt: Scalars['DateTime']['output'];
};
export type DeviceRunSessionMutation = {
__typename?: 'DeviceRunSessionMutation';
/** Create a device run session */
createDeviceRunSession: DeviceRunSession;
/** Stop a device run session */
stopDeviceRunSession: DeviceRunSession;
};
export type DeviceRunSessionMutationCreateDeviceRunSessionArgs = {
deviceRunSessionInput: CreateDeviceRunSessionInput;
};
export type DeviceRunSessionMutationStopDeviceRunSessionArgs = {
deviceRunSessionId: Scalars['ID']['input'];
};
export type DeviceRunSessionQuery = {
__typename?: 'DeviceRunSessionQuery';
byId: DeviceRunSession;
};
export type DeviceRunSessionQueryByIdArgs = {
deviceRunSessionId: Scalars['ID']['input'];
};
export enum DeviceRunSessionStatus {
Errored = 'ERRORED',
InProgress = 'IN_PROGRESS',
New = 'NEW',
Stopped = 'STOPPED'
}
export enum DeviceRunSessionType {
AgentDevice = 'AGENT_DEVICE'
}
export type DiscordUser = {
__typename?: 'DiscordUser';
discordIdentifier: Scalars['String']['output'];
@@ -5523,6 +5752,8 @@ export enum EntityTypeName {
BillingContractEntity = 'BillingContractEntity',
BranchEntity = 'BranchEntity',
ChannelEntity = 'ChannelEntity',
ConvexProjectEntity = 'ConvexProjectEntity',
ConvexTeamConnectionEntity = 'ConvexTeamConnectionEntity',
CustomerEntity = 'CustomerEntity',
EchoProjectEntity = 'EchoProjectEntity',
EchoVersionEntity = 'EchoVersionEntity',
@@ -7610,6 +7841,8 @@ export type RootMutation = {
deployments: DeploymentsMutation;
/** Mutations that assign or modify DevDomainNames for apps */
devDomainName: AppDevDomainNameMutation;
/** Mutations that create and stop device run sessions */
deviceRunSession: DeviceRunSessionMutation;
/** Mutations for Discord users */
discordUser: DiscordUserMutation;
/** Mutations for Echo chats */
@@ -7745,6 +7978,8 @@ export type RootQuery = {
appStoreConnectApiKey: AppStoreConnectApiKeyQuery;
/** Top-level query object for querying Apple Device registration requests. */
appleDeviceRegistrationRequest: AppleDeviceRegistrationRequestQuery;
/** Top-level query object for querying AppleDeviceRegistrationRequest publicly. */
appleDeviceRegistrationRequestPublicData: AppleDeviceRegistrationRequestPublicDataQuery;
/** Top-level query object for querying Apple distribution certificates. */
appleDistributionCertificate?: Maybe<AppleDistributionCertificateQuery>;
/** Top-level query object for querying Apple provisioning profiles. */
@@ -7768,6 +8003,7 @@ export type RootQuery = {
convexIntegration: ConvexIntegrationQuery;
/** Top-level query object for querying Deployments. */
deployments: DeploymentQuery;
deviceRunSessions: DeviceRunSessionQuery;
/** Top-level query object for querying Echo chats. */
echoChat: EchoChatQuery;
/** Top-level query object for querying Echo messages. */
@@ -11654,6 +11890,20 @@ export type RetryIosBuildMutationVariables = Exact<{
export type RetryIosBuildMutation = { __typename?: 'RootMutation', build: { __typename?: 'BuildMutation', retryIosBuild: { __typename?: 'Build', id: string, status: BuildStatus, platform: AppPlatform, logFiles: Array<string>, channel?: string | null, distribution?: DistributionType | null, iosEnterpriseProvisioning?: BuildIosEnterpriseProvisioning | null, buildProfile?: string | null, sdkVersion?: string | null, appVersion?: string | null, appBuildVersion?: string | null, runtimeVersion?: string | null, gitCommitHash?: string | null, gitCommitMessage?: string | null, initialQueuePosition?: number | null, queuePosition?: number | null, estimatedWaitTimeLeftSeconds?: number | null, priority: BuildPriority, createdAt: any, updatedAt: any, message?: string | null, completedAt?: any | null, expirationDate?: any | null, isForIosSimulator: boolean, error?: { __typename?: 'BuildError', errorCode: string, message: string, docsUrl?: string | null } | null, artifacts?: { __typename?: 'BuildArtifacts', buildUrl?: string | null, xcodeBuildLogsUrl?: string | null, applicationArchiveUrl?: string | null, buildArtifactsUrl?: string | null } | null, fingerprint?: { __typename?: 'Fingerprint', id: string, hash: string } | null, initiatingActor?: { __typename: 'PartnerActor', id: string, displayName: string } | { __typename: 'Robot', id: string, displayName: string } | { __typename: 'SSOUser', id: string, displayName: string } | { __typename: 'User', id: string, displayName: string } | null, project: { __typename: 'App', id: string, name: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } } | { __typename: 'Snack', id: string, name: string, slug: string }, metrics?: { __typename?: 'BuildMetrics', buildWaitTime?: number | null, buildQueueTime?: number | null, buildDuration?: number | null } | null } } };
export type CreateDeviceRunSessionMutationVariables = Exact<{
deviceRunSessionInput: CreateDeviceRunSessionInput;
}>;
export type CreateDeviceRunSessionMutation = { __typename?: 'RootMutation', deviceRunSession: { __typename?: 'DeviceRunSessionMutation', createDeviceRunSession: { __typename?: 'DeviceRunSession', id: string, status: DeviceRunSessionStatus, app: { __typename?: 'App', id: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string } }, turtleJobRun?: { __typename?: 'JobRun', id: string } | null } } };
export type StopDeviceRunSessionMutationVariables = Exact<{
deviceRunSessionId: Scalars['ID']['input'];
}>;
export type StopDeviceRunSessionMutation = { __typename?: 'RootMutation', deviceRunSession: { __typename?: 'DeviceRunSessionMutation', stopDeviceRunSession: { __typename?: 'DeviceRunSession', id: string, status: DeviceRunSessionStatus } } };
export type CreateEnvironmentSecretForAccountMutationVariables = Exact<{
input: CreateEnvironmentSecretInput;
accountId: Scalars['String']['input'];
@@ -12106,6 +12356,13 @@ export type ViewUpdateChannelsPaginatedOnAppQueryVariables = Exact<{
export type ViewUpdateChannelsPaginatedOnAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, channelsPaginated: { __typename?: 'AppChannelsConnection', edges: Array<{ __typename?: 'AppChannelEdge', cursor: string, node: { __typename?: 'UpdateChannel', id: string, name: string, branchMapping: string } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null, endCursor?: string | null } } } } };
export type DeviceRunSessionByIdQueryVariables = Exact<{
deviceRunSessionId: Scalars['ID']['input'];
}>;
export type DeviceRunSessionByIdQuery = { __typename?: 'RootQuery', deviceRunSessions: { __typename?: 'DeviceRunSessionQuery', byId: { __typename?: 'DeviceRunSession', id: string, status: DeviceRunSessionStatus, turtleJobRun?: { __typename?: 'JobRun', id: string, status: JobRunStatus, logFileUrls: Array<string> } | null } } };
export type EnvironmentSecretsByAppIdQueryVariables = Exact<{
appId: Scalars['String']['input'];
}>;
@@ -0,0 +1,73 @@
import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../client';
import {
CreateDeviceRunSessionInput,
CreateDeviceRunSessionMutation,
CreateDeviceRunSessionMutationVariables,
StopDeviceRunSessionMutation,
StopDeviceRunSessionMutationVariables,
} from '../generated';
export const DeviceRunSessionMutation = {
async createDeviceRunSessionAsync(
graphqlClient: ExpoGraphqlClient,
deviceRunSessionInput: CreateDeviceRunSessionInput
): Promise<CreateDeviceRunSessionMutation['deviceRunSession']['createDeviceRunSession']> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<CreateDeviceRunSessionMutation, CreateDeviceRunSessionMutationVariables>(
gql`
mutation CreateDeviceRunSessionMutation($deviceRunSessionInput: CreateDeviceRunSessionInput!) {
deviceRunSession {
createDeviceRunSession(deviceRunSessionInput: $deviceRunSessionInput) {
id
status
app {
id
slug
ownerAccount {
id
name
}
}
turtleJobRun {
id
}
}
}
}
`,
{ deviceRunSessionInput },
{ noRetry: true }
)
.toPromise()
);
return data.deviceRunSession.createDeviceRunSession;
},
async stopDeviceRunSessionAsync(
graphqlClient: ExpoGraphqlClient,
deviceRunSessionId: string
): Promise<StopDeviceRunSessionMutation['deviceRunSession']['stopDeviceRunSession']> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<StopDeviceRunSessionMutation, StopDeviceRunSessionMutationVariables>(
gql`
mutation StopDeviceRunSessionMutation($deviceRunSessionId: ID!) {
deviceRunSession {
stopDeviceRunSession(deviceRunSessionId: $deviceRunSessionId) {
id
status
}
}
}
`,
{ deviceRunSessionId },
{ noRetry: true }
)
.toPromise()
);
return data.deviceRunSession.stopDeviceRunSession;
},
};
@@ -0,0 +1,37 @@
import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../client';
import { DeviceRunSessionByIdQuery, DeviceRunSessionByIdQueryVariables } from '../generated';
export const DeviceRunSessionQuery = {
async byIdAsync(
graphqlClient: ExpoGraphqlClient,
deviceRunSessionId: string
): Promise<DeviceRunSessionByIdQuery['deviceRunSessions']['byId']> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<DeviceRunSessionByIdQuery, DeviceRunSessionByIdQueryVariables>(
gql`
query DeviceRunSessionByIdQuery($deviceRunSessionId: ID!) {
deviceRunSessions {
byId(deviceRunSessionId: $deviceRunSessionId) {
id
status
turtleJobRun {
id
status
logFileUrls
}
}
}
}
`,
{ deviceRunSessionId },
{ requestPolicy: 'network-only' }
)
.toPromise()
);
return data.deviceRunSessions.byId;
},
};
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "eas-cli-local-build-plugin",
"version": "18.8.0",
"version": "18.8.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,7 +26,7 @@
"clean": "rimraf node_modules dist coverage \"*.tsbuildinfo\""
},
"dependencies": {
"@expo/build-tools": "18.8.0",
"@expo/build-tools": "18.8.1",
"@expo/eas-build-job": "18.8.0",
"@expo/logger": "18.5.0",
"@expo/spawn-async": "^1.7.2",
@@ -0,0 +1,83 @@
import { JobInterpolationContext } from '@expo/eas-build-job';
import { interpolateJobContext } from '../interpolation';
const context = {
inputs: {
profile: 'production',
flags: { quiet: true, retries: 3 },
},
github: {
event: {
pull_request: {
html_url: 'https://github.com/foo/bar/pull/42',
title: 'Add cool feature',
},
},
},
} as unknown as JobInterpolationContext;
describe(interpolateJobContext, () => {
test('single expression value preserves the underlying type', () => {
const result = interpolateJobContext({
target: '${{ inputs.flags }}',
context,
});
expect(result).toEqual({ quiet: true, retries: 3 });
});
test('single expression value resolves to a string', () => {
const result = interpolateJobContext({
target: '${{ inputs.profile }}',
context,
});
expect(result).toBe('production');
});
test('multiple expressions in one value are each replaced with their string result', () => {
const result = interpolateJobContext({
target:
'${{ github.event.pull_request.html_url }}: ${{ github.event.pull_request.title }}',
context,
});
expect(result).toBe('https://github.com/foo/bar/pull/42: Add cool feature');
});
test('plain text is returned unchanged', () => {
const result = interpolateJobContext({ target: 'just text', context });
expect(result).toBe('just text');
});
test('expression with text around it is interpolated as a string', () => {
const result = interpolateJobContext({
target: 'profile=${{ inputs.profile }}',
context,
});
expect(result).toBe('profile=production');
});
test('object values recurse', () => {
const result = interpolateJobContext({
target: { profile: '${{ inputs.profile }}', literal: 'x' },
context,
});
expect(result).toEqual({ profile: 'production', literal: 'x' });
});
test('array values recurse', () => {
const result = interpolateJobContext({
target: ['${{ inputs.profile }}', 'literal'],
context,
});
expect(result).toEqual(['production', 'literal']);
});
test('string concatenation inside a single expression', () => {
const result = interpolateJobContext({
target:
"${{ github.event.pull_request.html_url + ': ' + github.event.pull_request.title }}",
context,
});
expect(result).toBe('https://github.com/foo/bar/pull/42: Add cool feature');
});
});
+13 -3
View File
@@ -10,9 +10,19 @@ export function interpolateJobContext({
context: JobInterpolationContext;
}): unknown {
if (typeof target === 'string') {
// If the value is e.g. `build: ${{ inputs.build }}`, we will interpolate the value
// without changing `inputs.build` type, i.e. if it is an object it'll be like `build: {...inputs.build}`.
if (target.startsWith('${{') && target.endsWith('}}')) {
// If the value is exactly one `${{ ... }}` expression, we interpolate it without
// changing the result's type, i.e. if `inputs.build` is an object then
// `build: ${{ inputs.build }}` becomes `build: {...inputs.build}`.
//
// `startsWith('${{') && endsWith('}}')` alone is not enough: a value like
// `${{ a }}: ${{ b }}` also starts with `${{` and ends with `}}`, but those
// delimiters are not a matched pair. We must also confirm there's no second
// `${{` after the opening one.
if (
target.startsWith('${{') &&
target.endsWith('}}') &&
target.indexOf('${{', 3) === -1
) {
return jsepEval(target.slice(3, -2), context);
}
@@ -14,3 +14,4 @@ if (!process.env.LISTENING_TO_UNHANDLED_REJECTION) {
// Always mock:
jest.mock('../src/CacheManager');
jest.mock('../src/utils/turtleFetch');
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@expo/worker",
"version": "18.8.0",
"version": "18.8.1",
"private": true,
"scripts": {
"start": "yarn watch",
@@ -19,7 +19,7 @@
},
"dependencies": {
"@babel/core": "7.24.7",
"@expo/build-tools": "18.8.0",
"@expo/build-tools": "18.8.1",
"@expo/config-plugins": "55.0.7",
"@expo/config-types": "55.0.5",
"@expo/downloader": "18.5.0",
@@ -70,6 +70,7 @@ jest.mock('../config', () => {
default: {
...config.default,
buildId: 'e9b99e52-fb74-4927-be63-33d7447ddfd4',
wwwApiV2BaseUrl: 'http://api.expo.test/v2/',
},
};
});
@@ -40,6 +40,7 @@ jest.mock('../config', () => {
return {
...config,
buildId: 'e9b99e52-fb74-4927-be63-33d7447ddfd4',
wwwApiV2BaseUrl: 'http://api.expo.test/v2/',
};
});
@@ -40,6 +40,7 @@ jest.mock('../config', () => {
return {
...config,
buildId: 'f38532aa-81a8-4db7-915f-6e7afe46e22f',
wwwApiV2BaseUrl: 'http://api.expo.test/v2/',
};
});
@@ -77,6 +77,7 @@ jest.mock('../config', () => {
return {
...config,
buildId: 'e9b99e52-fb74-4927-be63-33d7447ddfd4',
wwwApiV2BaseUrl: 'http://api.expo.test/v2/',
};
});
jest.mock('../upload', () => {
+32
View File
@@ -5,9 +5,11 @@ import { getBuildEnv } from '../env';
describe(getBuildEnv.name, () => {
const originalSentryDsn = config.sentry.dsn;
const originalCocoapodsCacheUrl = config.cocoapodsCacheUrl;
afterEach(() => {
config.sentry.dsn = originalSentryDsn;
config.cocoapodsCacheUrl = originalCocoapodsCacheUrl;
});
it('passes the CLI sentry DSN to worker child processes', () => {
@@ -55,6 +57,36 @@ describe(getBuildEnv.name, () => {
});
expect(env.EXPO_USE_PRECOMPILED_MODULES).toBe('1');
expect(env.EXPO_PRECOMPILED_MODULES_BASE_URL).toBe(
'https://storage.googleapis.com/eas-build-precompiled-modules/'
);
expect(env.EXPO_PRECOMPILED_MODULES_PATH).toBeUndefined();
});
it('passes precompiled modules through the CocoaPods cache URL when available', () => {
config.cocoapodsCacheUrl = 'https://cache.example.com';
const env = getBuildEnv({
job: {
platform: Platform.IOS,
type: Workflow.GENERIC,
builderEnvironment: {
env: {
EAS_USE_PRECOMPILED_MODULES: '1',
},
},
} as any,
projectId: 'project-id',
metadata: {
buildProfile: 'production',
gitCommitHash: 'abc123',
username: 'expo-user',
} as any,
buildId: 'build-id',
});
expect(env.EXPO_PRECOMPILED_MODULES_BASE_URL).toBe(
'https://cache.example.com/storage.googleapis.com/eas-build-precompiled-modules/'
);
});
});
+16
View File
@@ -12,6 +12,9 @@ import {
} from './external/turtle';
import { getAccessedEnvs } from './utils/env';
const PRECOMPILED_MODULES_BASE_URL =
'https://storage.googleapis.com/eas-build-precompiled-modules/';
// keep in sync with local-build-plugin env vars
// see packages/local-build-plugin/src/build.ts
export function getBuildEnv({
@@ -55,6 +58,7 @@ export function getBuildEnv({
setEnv(env, 'COMPILER_INDEX_STORE_ENABLE', 'NO');
if (job.builderEnvironment?.env?.EAS_USE_PRECOMPILED_MODULES === '1') {
setEnv(env, 'EXPO_USE_PRECOMPILED_MODULES', '1');
setEnv(env, 'EXPO_PRECOMPILED_MODULES_BASE_URL', getPrecompiledModulesBaseUrl());
}
if (job.builderEnvironment?.env?.EAS_USE_CACHE === '1') {
@@ -166,6 +170,18 @@ function setEnv(env: Env, key: string, value: string | null | undefined): void {
}
}
function getPrecompiledModulesBaseUrl(): string {
if (!config.cocoapodsCacheUrl) {
return PRECOMPILED_MODULES_BASE_URL;
}
const parsedUrl = new URL(PRECOMPILED_MODULES_BASE_URL);
return PRECOMPILED_MODULES_BASE_URL.replace(
`${parsedUrl.protocol}//${parsedUrl.host}`,
`${config.cocoapodsCacheUrl.replace(/\/$/, '')}/${parsedUrl.host}`
);
}
const ResourceClassToMaxHeapSize: Record<ResourceClass, string | null> = {
[ResourceClass.LINUX_C3D_STANDARD_4]: '4g', // 4 out of 16 GB, 12 GB left
[ResourceClass.LINUX_C3D_STANDARD_8]: '8g', // 8 out of 32 GB, 24 GB left
+36 -17
View File
@@ -332,7 +332,7 @@ export default class BuildService {
});
const robotAccessToken = job.secrets?.robotAccessToken;
if (robotAccessToken && err.errorCode === errors.ErrorCode.UNKNOWN_ERROR) {
if (robotAccessToken) {
let rawErrorMessage: string = '';
if (maybeRawError?.stderr) {
rawErrorMessage += '\n' + getLastNLines(100, maybeRawError.stderr);
@@ -340,23 +340,42 @@ export default class BuildService {
if (maybeRawError?.stdout) {
rawErrorMessage += '\n' + getLastNLines(100, maybeRawError.stdout);
}
if (!rawErrorMessage) {
rawErrorMessage = maybeRawError?.message ?? err.message;
}
await turtleFetch(
new URL('turtle-builds/error-logs', config.wwwApiV2BaseUrl).toString(),
'POST',
{
json: {
buildId: this.buildId,
message: rawErrorMessage,
buildPhase: err.buildPhase ?? null,
errorCode: err.errorCode,
},
headers: {
Authorization: `Bearer ${robotAccessToken}`,
},
shouldThrowOnNotOk: false,
}
);
try {
await turtleFetch(
new URL('turtle-builds/error-logs', config.wwwApiV2BaseUrl).toString(),
'POST',
{
json: {
buildId: this.buildId,
message: rawErrorMessage,
buildPhase: err.buildPhase ?? null,
errorCode: err.errorCode,
tags: {
platform: job.platform,
workflow: job.type,
sdk_version: metadata?.sdkVersion ?? null,
react_native_version: metadata?.reactNativeVersion ?? null,
app_id: job.appId ?? null,
build_profile: metadata?.buildProfile ?? null,
app_name: metadata?.appName ?? null,
app_identifier: metadata?.appIdentifier ?? null,
distribution: metadata?.distribution ?? null,
cli_version: metadata?.cliVersion ?? null,
},
},
headers: {
Authorization: `Bearer ${robotAccessToken}`,
},
shouldThrowOnNotOk: false,
}
);
} catch (fetchError: any) {
logger.warn({ err: fetchError }, 'Failed to send build error log');
}
}
await this.finishError(err, maybeArtifacts);
Generated
+3 -3
View File
@@ -2856,7 +2856,7 @@ __metadata:
languageName: node
linkType: hard
"@expo/build-tools@npm:18.8.0, @expo/build-tools@workspace:packages/build-tools":
"@expo/build-tools@npm:18.8.1, @expo/build-tools@workspace:packages/build-tools":
version: 0.0.0-use.local
resolution: "@expo/build-tools@workspace:packages/build-tools"
dependencies:
@@ -3554,7 +3554,7 @@ __metadata:
resolution: "@expo/worker@workspace:packages/worker"
dependencies:
"@babel/core": "npm:7.24.7"
"@expo/build-tools": "npm:18.8.0"
"@expo/build-tools": "npm:18.8.1"
"@expo/config-plugins": "npm:55.0.7"
"@expo/config-types": "npm:55.0.5"
"@expo/downloader": "npm:18.5.0"
@@ -10944,7 +10944,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "eas-cli-local-build-plugin@workspace:packages/local-build-plugin"
dependencies:
"@expo/build-tools": "npm:18.8.0"
"@expo/build-tools": "npm:18.8.1"
"@expo/eas-build-job": "npm:18.8.0"
"@expo/logger": "npm:18.5.0"
"@expo/spawn-async": "npm:^1.7.2"