@expo/build-tools 23.2.0 → 24.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/common/projectSources.js +4 -2
  2. package/dist/context.d.ts +2 -0
  3. package/dist/context.js +2 -0
  4. package/dist/customBuildContext.d.ts +1 -0
  5. package/dist/customBuildContext.js +2 -0
  6. package/dist/generic.js +11 -1
  7. package/dist/steps/easFunctions.js +2 -0
  8. package/dist/steps/functions/startAgentDeviceRemoteSession.js +7 -3
  9. package/dist/steps/functions/startAndroidEmulator.js +21 -0
  10. package/dist/steps/functions/startAppiumRemoteSession.js +7 -3
  11. package/dist/steps/functions/startArgentRemoteSession.js +26 -15
  12. package/dist/steps/functions/startLocalEgress.d.ts +10 -0
  13. package/dist/steps/functions/startLocalEgress.js +156 -0
  14. package/dist/steps/functions/startWebPreviewRemoteSession.js +10 -4
  15. package/dist/steps/functions/uploadToAsc.js +11 -5
  16. package/dist/steps/utils/appiumCommandSummary.js +3 -0
  17. package/dist/steps/utils/appiumCommands.generated.d.ts +2 -2
  18. package/dist/steps/utils/localEgress.d.ts +152 -0
  19. package/dist/steps/utils/localEgress.js +550 -0
  20. package/dist/steps/utils/localEgressSession.d.ts +9 -0
  21. package/dist/steps/utils/localEgressSession.js +40 -0
  22. package/dist/steps/utils/remoteDeviceRunSession.d.ts +8 -18
  23. package/dist/steps/utils/remoteDeviceRunSession.js +66 -21
  24. package/dist/steps/utils/serveSimMetricsRecorder.d.ts +4 -1
  25. package/dist/steps/utils/serveSimMetricsRecorder.js +14 -6
  26. package/dist/utils/AndroidEmulatorUtils.d.ts +4 -1
  27. package/dist/utils/AndroidEmulatorUtils.js +5 -1
  28. package/dist/utils/logPhase.d.ts +2 -0
  29. package/dist/utils/logPhase.js +22 -0
  30. package/package.json +8 -8
@@ -41,7 +41,7 @@ exports.getNgrokTunnelDomainOrThrow = getNgrokTunnelDomainOrThrow;
41
41
  exports.getNgrokAuthtokenOrThrow = getNgrokAuthtokenOrThrow;
42
42
  exports.selectXcodeDeveloperDirectoryAsync = selectXcodeDeveloperDirectoryAsync;
43
43
  exports.waitForDeviceRunSessionStoppedAsync = waitForDeviceRunSessionStoppedAsync;
44
- exports.ensureFfmpegInstalledAsync = ensureFfmpegInstalledAsync;
44
+ exports.ensureFfmpegInstalledOnceAsync = ensureFfmpegInstalledOnceAsync;
45
45
  exports.turnIceServersToWebPreviewArgs = turnIceServersToWebPreviewArgs;
46
46
  exports.fetchWebPreviewTurnArgsAsync = fetchWebPreviewTurnArgsAsync;
47
47
  exports.uploadRemoteSessionConfigAsync = uploadRemoteSessionConfigAsync;
@@ -49,7 +49,9 @@ exports.spawnDetached = spawnDetached;
49
49
  exports.metricsCorsOriginToServeSimArgs = metricsCorsOriginToServeSimArgs;
50
50
  exports.createServeSimArgs = createServeSimArgs;
51
51
  exports.createExpoDeviceHubArgs = createExpoDeviceHubArgs;
52
+ exports.findAvailablePortAsync = findAvailablePortAsync;
52
53
  exports.waitForWebPreviewReadyAsync = waitForWebPreviewReadyAsync;
54
+ exports.readServeSimPreviewTokenAsync = readServeSimPreviewTokenAsync;
53
55
  exports.startServeSimWithTunnelAsync = startServeSimWithTunnelAsync;
54
56
  exports.startExpoDeviceHubWithTunnelAsync = startExpoDeviceHubWithTunnelAsync;
55
57
  exports.startDeviceWebPreviewWithTunnelAsync = startDeviceWebPreviewWithTunnelAsync;
@@ -71,6 +73,7 @@ const promises_1 = require("node:timers/promises");
71
73
  const sentry_1 = require("../../sentry");
72
74
  const retry_1 = require("../../utils/retry");
73
75
  const turtleFetch_1 = require("../../utils/turtleFetch");
76
+ const serveSimMetricsRecorder_1 = require("./serveSimMetricsRecorder");
74
77
  const XCODE_DEVELOPER_DIR = '/Applications/Xcode.app/Contents/Developer';
75
78
  const WEB_PREVIEW_HOST = '127.0.0.1';
76
79
  const SERVE_SIM_PACKAGE_NAME = '@expo/serve-sim';
@@ -79,7 +82,7 @@ const SERVE_SIM_MJPEG_QUALITY = '0.55';
79
82
  const SERVE_SIM_VIDEO_BITRATE = '6000000';
80
83
  const SERVE_SIM_VIDEO_FPS = '60';
81
84
  const EXPO_DEVICE_HUB_PACKAGE_NAME = 'expo-device-hub';
82
- const EXPO_DEVICE_HUB_MAX_DIMENSION = '1280';
85
+ const EXPO_DEVICE_HUB_MAX_DIMENSION = '960';
83
86
  const EXPO_DEVICE_HUB_VIDEO_BITRATE = '6000000';
84
87
  const EXPO_DEVICE_HUB_VIDEO_FPS = '60';
85
88
  const START_DEVICE_RUN_SESSION_MUTATION = (0, gql_tada_1.graphql)(`
@@ -269,10 +272,9 @@ async function sleepUntilAbortedAsync(timeoutMs, signal) {
269
272
  }
270
273
  }
271
274
  }
272
- // Argent encodes screen recordings by piping simulator frames into `ffmpeg`,
273
- // which it resolves from PATH. The tool-server inherits this step's env, so
274
- // spawning ffmpeg resolves against the same PATH argent will search: it rejects
275
- // with ENOENT when the binary is absent, and running it also proves it works.
275
+ // Device-session tools resolve `ffmpeg` from PATH. Spawning it with the step's
276
+ // environment rejects with ENOENT when the binary is absent, and running it also
277
+ // proves that the installed binary works.
276
278
  async function isFfmpegAvailableAsync(env) {
277
279
  return (await (0, results_1.asyncResult)((0, turtle_spawn_1.default)('ffmpeg', ['-version'], { env }))).ok;
278
280
  }
@@ -290,14 +292,14 @@ async function installFfmpegWithAptAsync({ env, logger, }) {
290
292
  await (0, results_1.asyncResult)((0, turtle_spawn_1.default)('sudo', ['apt-get', 'update'], { env: aptEnv, logger }));
291
293
  await (0, turtle_spawn_1.default)('sudo', ['apt-get', 'install', '-y', 'ffmpeg'], { env: aptEnv, logger });
292
294
  }
295
+ let ffmpegSetupPromise;
293
296
  /**
294
- * Install ffmpeg when the runtime does not already provide it, so argent's
295
- * `screen-recording-start` tool can encode a video. The worker images do not
296
- * ship ffmpeg yet, so without this the tool fails with "`ffmpeg` was not found
297
- * on PATH" — on macOS (iOS simulators) and Linux (Android emulators) alike.
297
+ * Install ffmpeg when the runtime does not already provide it. Device-session
298
+ * tools use it for video encoding on macOS (iOS simulators) and Linux (Android
299
+ * emulators) alike, but the worker images do not ship it yet.
298
300
  *
299
- * Best-effort by design: screen recording is one optional argent tool, so a
300
- * failure here is logged and the session continues without it.
301
+ * Best-effort by design: a failure here is logged and the session continues
302
+ * without FFmpeg-dependent features.
301
303
  *
302
304
  * The whole body is wrapped because the caller runs this in the background with
303
305
  * `void`. There is no unhandledRejection handler in the worker, so a rejection
@@ -312,7 +314,7 @@ async function ensureFfmpegInstalledAsync({ runtimePlatform, env, logger, }) {
312
314
  return;
313
315
  }
314
316
  const isDarwin = runtimePlatform === steps_1.BuildRuntimePlatform.DARWIN;
315
- logger.info(`ffmpeg is not installed, installing it with ${isDarwin ? 'Homebrew' : 'apt'} for argent screen recording.`);
317
+ logger.info(`ffmpeg is not installed, installing it with ${isDarwin ? 'Homebrew' : 'apt'} for the device session.`);
316
318
  if (isDarwin) {
317
319
  await installFfmpegWithHomebrewAsync({ env, logger });
318
320
  }
@@ -323,10 +325,26 @@ async function ensureFfmpegInstalledAsync({ runtimePlatform, env, logger, }) {
323
325
  }
324
326
  catch (err) {
325
327
  const error = err instanceof Error ? err : new Error(String(err));
326
- sentry_1.Sentry.capture('Could not install ffmpeg for argent screen recording', error, {
328
+ sentry_1.Sentry.capture('Could not install ffmpeg for the device session', error, {
327
329
  level: 'warning',
328
330
  });
329
- logger.warn({ err: error }, 'Could not install ffmpeg. Argent screen recording will not work in this session.');
331
+ logger.warn({ err: error }, 'Could not install ffmpeg. FFmpeg-dependent features may not work in this session.');
332
+ }
333
+ }
334
+ async function ensureFfmpegInstalledOnceAsync({ runtimePlatform, env, logger, }) {
335
+ if (ffmpegSetupPromise) {
336
+ await ffmpegSetupPromise;
337
+ return;
338
+ }
339
+ const setupPromise = ensureFfmpegInstalledAsync({ runtimePlatform, env, logger });
340
+ ffmpegSetupPromise = setupPromise;
341
+ try {
342
+ await setupPromise;
343
+ }
344
+ finally {
345
+ if (ffmpegSetupPromise === setupPromise) {
346
+ ffmpegSetupPromise = undefined;
347
+ }
330
348
  }
331
349
  }
332
350
  const TurnIceServersResponseSchema = zod_1.z.object({
@@ -495,6 +513,7 @@ function createServeSimArgs({ port, turnArgs = [], metricsCorsArgs = [], package
495
513
  String(port),
496
514
  '--host',
497
515
  WEB_PREVIEW_HOST,
516
+ '--require-token',
498
517
  '--transport',
499
518
  'webrtc',
500
519
  '--webrtc-codec',
@@ -571,8 +590,8 @@ async function waitForWebPreviewReadyAsync({ previewServer, serverName, port, ti
571
590
  retries: 0,
572
591
  timeout: 2_000,
573
592
  });
574
- WebPreviewReadyResponseSchema.parse(await response.json());
575
- return;
593
+ const ready = WebPreviewReadyResponseSchema.parse(await response.json());
594
+ return ready.device;
576
595
  }
577
596
  catch (error) {
578
597
  lastError = error;
@@ -581,7 +600,7 @@ async function waitForWebPreviewReadyAsync({ previewServer, serverName, port, ti
581
600
  }
582
601
  throw new eas_build_job_1.SystemError(`Timed out waiting for ${serverName} readiness at ${readyUrl}${lastError instanceof Error ? `: ${lastError.message}` : ''}. Last output:\n${previewServer.getOutput() || '<empty>'}`);
583
602
  }
584
- async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, timeoutMs, serverName, packageSpec, createArgs, }) {
603
+ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, timeoutMs, serverName, packageSpec, createArgs, readPreviewTokenAsync, }) {
585
604
  const port = await findAvailablePortAsync();
586
605
  logger.info(`Launching ${packageSpec} on ${WEB_PREVIEW_HOST}:${port}.`);
587
606
  const turnArgs = await fetchWebPreviewTurnArgsAsync(ctx, { env, logger });
@@ -592,7 +611,13 @@ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, ti
592
611
  });
593
612
  try {
594
613
  logger.info(`Waiting for ${serverName} to become ready.`);
595
- await waitForWebPreviewReadyAsync({ previewServer, serverName, port, timeoutMs });
614
+ const device = await waitForWebPreviewReadyAsync({
615
+ previewServer,
616
+ serverName,
617
+ port,
618
+ timeoutMs,
619
+ });
620
+ const previewToken = await readPreviewTokenAsync?.(device);
596
621
  const tunnel = await startNgrokTunnelAsync({
597
622
  port,
598
623
  subdomainPrefix: 'web-preview',
@@ -602,6 +627,7 @@ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, ti
602
627
  });
603
628
  return {
604
629
  previewUrl: tunnel.url,
630
+ previewToken,
605
631
  stopAsync: async () => {
606
632
  const results = await Promise.allSettled([tunnel.stopAsync(), previewServer.stopAsync()]);
607
633
  for (const result of results) {
@@ -617,6 +643,10 @@ async function startWebPreviewWithTunnelAsync(ctx, { baseDomain, env, logger, ti
617
643
  throw error;
618
644
  }
619
645
  }
646
+ async function readServeSimPreviewTokenAsync(udid, stateDir = serveSimMetricsRecorder_1.SERVE_SIM_STATE_DIR) {
647
+ const servers = await (0, serveSimMetricsRecorder_1.readServeSimServersAsync)(stateDir);
648
+ return servers.find(server => server.udid === udid)?.token;
649
+ }
620
650
  async function startServeSimWithTunnelAsync(ctx, { baseDomain, env, logger, timeoutMs, packageVersion, }) {
621
651
  const metricsCorsArgs = metricsCorsOriginToServeSimArgs(env);
622
652
  return await startWebPreviewWithTunnelAsync(ctx, {
@@ -627,9 +657,24 @@ async function startServeSimWithTunnelAsync(ctx, { baseDomain, env, logger, time
627
657
  serverName: 'serve-sim',
628
658
  packageSpec: createServeSimPackageSpec(packageVersion),
629
659
  createArgs: (port, turnArgs) => createServeSimArgs({ port, turnArgs, metricsCorsArgs, packageVersion }),
660
+ readPreviewTokenAsync: async (device) => {
661
+ const previewToken = await readServeSimPreviewTokenAsync(device);
662
+ if (!previewToken) {
663
+ // A serve-sim that does not know --require-token fails earlier, in the readiness check, so
664
+ // reaching here means it started and left no token in its state file.
665
+ throw new eas_build_job_1.SystemError(`serve-sim became ready but wrote no session token for device ${device}. The preview is ` +
666
+ 'on a public tunnel and would be reachable without one, so the session cannot continue. ' +
667
+ 'This usually means the state file was not written as expected; retry the session, and ' +
668
+ 'report it if it repeats.');
669
+ }
670
+ return previewToken;
671
+ },
630
672
  });
631
673
  }
632
- async function startExpoDeviceHubWithTunnelAsync(ctx, { baseDomain, env, logger, timeoutMs, packageVersion, }) {
674
+ async function startExpoDeviceHubWithTunnelAsync(ctx, { runtimePlatform, baseDomain, env, logger, timeoutMs, packageVersion, }) {
675
+ if (runtimePlatform === steps_1.BuildRuntimePlatform.LINUX) {
676
+ await ensureFfmpegInstalledOnceAsync({ runtimePlatform, env, logger });
677
+ }
633
678
  return await startWebPreviewWithTunnelAsync(ctx, {
634
679
  baseDomain,
635
680
  env,
@@ -645,7 +690,7 @@ async function startDeviceWebPreviewWithTunnelAsync(ctx, { runtimePlatform, ...o
645
690
  case steps_1.BuildRuntimePlatform.DARWIN:
646
691
  return await startServeSimWithTunnelAsync(ctx, options);
647
692
  case steps_1.BuildRuntimePlatform.LINUX:
648
- return await startExpoDeviceHubWithTunnelAsync(ctx, options);
693
+ return await startExpoDeviceHubWithTunnelAsync(ctx, { ...options, runtimePlatform });
649
694
  }
650
695
  }
651
696
  async function startNgrokTunnelAsync({ port, subdomainPrefix, baseDomain, authtoken, rewriteHostHeader, logger, }) {
@@ -1,7 +1,9 @@
1
1
  import { type bunyan } from '@expo/logger';
2
+ export declare const SERVE_SIM_STATE_DIR: string;
2
3
  type ServeSimServer = {
3
4
  udid: string;
4
5
  url: string;
6
+ token?: string;
5
7
  };
6
8
  export declare namespace ServeSimMetricsRecorder {
7
9
  function startAsync({ logger, stateDir, pollIntervalMs, }: {
@@ -18,8 +20,9 @@ export declare namespace ServeSimMetricsRecorder {
18
20
  }[]>;
19
21
  }
20
22
  export declare function readServeSimServersAsync(stateDir: string): Promise<ServeSimServer[]>;
21
- export declare function streamServeSimMetricsToFileAsync({ serveSimUrl, filePath, signal, logger, }: {
23
+ export declare function streamServeSimMetricsToFileAsync({ serveSimUrl, serveSimToken, filePath, signal, logger, }: {
22
24
  serveSimUrl: string;
25
+ serveSimToken?: string;
23
26
  filePath: string;
24
27
  signal: AbortSignal;
25
28
  logger: bunyan;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ServeSimMetricsRecorder = void 0;
6
+ exports.ServeSimMetricsRecorder = exports.SERVE_SIM_STATE_DIR = void 0;
7
7
  exports.readServeSimServersAsync = readServeSimServersAsync;
8
8
  exports.streamServeSimMetricsToFileAsync = streamServeSimMetricsToFileAsync;
9
9
  const node_fetch_1 = __importDefault(require("node-fetch"));
@@ -18,11 +18,11 @@ const POLL_INTERVAL_MS = 2_000;
18
18
  const MAX_CONSECUTIVE_STREAM_FAILURES_PER_DEVICE = 10;
19
19
  const END_STREAM_TIMEOUT_MS = 2_000;
20
20
  // serve-sim's own per-device registry while serving: `${tmpdir}/serve-sim/server-<udid>.json`.
21
- const SERVE_SIM_STATE_DIR = node_path_1.default.join(node_os_1.default.tmpdir(), 'serve-sim');
21
+ exports.SERVE_SIM_STATE_DIR = node_path_1.default.join(node_os_1.default.tmpdir(), 'serve-sim');
22
22
  let activeSession = null;
23
23
  var ServeSimMetricsRecorder;
24
24
  (function (ServeSimMetricsRecorder) {
25
- async function startAsync({ logger, stateDir = SERVE_SIM_STATE_DIR, pollIntervalMs = POLL_INTERVAL_MS, }) {
25
+ async function startAsync({ logger, stateDir = exports.SERVE_SIM_STATE_DIR, pollIntervalMs = POLL_INTERVAL_MS, }) {
26
26
  if (activeSession) {
27
27
  logger.info('serve-sim metrics polling is already running.');
28
28
  return;
@@ -101,6 +101,7 @@ async function pollServeSimMetricsAsync(session) {
101
101
  logger.info(`Collecting serve-sim metrics for ${server.udid}.`);
102
102
  const donePromise = streamServeSimMetricsToFileAsync({
103
103
  serveSimUrl: server.url,
104
+ serveSimToken: server.token,
104
105
  filePath,
105
106
  signal: streamSignal,
106
107
  logger,
@@ -140,7 +141,11 @@ async function readServeSimServersAsync(stateDir) {
140
141
  try {
141
142
  const state = JSON.parse(await (0, promises_1.readFile)(node_path_1.default.join(stateDir, entry), 'utf-8'));
142
143
  if (typeof state.device === 'string' && typeof state.url === 'string') {
143
- servers.push({ udid: state.device, url: state.url });
144
+ servers.push({
145
+ udid: state.device,
146
+ url: state.url,
147
+ ...(typeof state.token === 'string' ? { token: state.token } : {}),
148
+ });
144
149
  }
145
150
  }
146
151
  catch {
@@ -149,7 +154,7 @@ async function readServeSimServersAsync(stateDir) {
149
154
  }
150
155
  return servers;
151
156
  }
152
- async function streamServeSimMetricsToFileAsync({ serveSimUrl, filePath, signal, logger, }) {
157
+ async function streamServeSimMetricsToFileAsync({ serveSimUrl, serveSimToken, filePath, signal, logger, }) {
153
158
  const file = (0, node_fs_1.createWriteStream)(filePath, { flags: 'a' });
154
159
  file.on('error', err => {
155
160
  logger.warn({ err }, `serve-sim metrics file write failed for ${filePath}.`);
@@ -157,7 +162,10 @@ async function streamServeSimMetricsToFileAsync({ serveSimUrl, filePath, signal,
157
162
  let receivedData = false;
158
163
  let metadata;
159
164
  try {
160
- const response = await (0, node_fetch_1.default)(new URL('/metrics', serveSimUrl).toString(), { signal });
165
+ const response = await (0, node_fetch_1.default)(new URL('/metrics', serveSimUrl).toString(), {
166
+ signal,
167
+ ...(serveSimToken ? { headers: { Authorization: `Bearer ${serveSimToken}` } } : {}),
168
+ });
161
169
  if (!response.ok || !response.body) {
162
170
  logger.warn(`serve-sim /metrics responded ${response.status} for ${serveSimUrl}.`);
163
171
  return { receivedData, metadata };
@@ -21,10 +21,13 @@ export declare namespace AndroidEmulatorUtils {
21
21
  deviceName: AndroidVirtualDeviceName;
22
22
  env: NodeJS.ProcessEnv;
23
23
  }): Promise<AndroidDeviceSerialId | null>;
24
- function createAsync({ deviceName, systemImagePackage, deviceIdentifier, env, logger, }: {
24
+ function createAsync({ deviceName, systemImagePackage, deviceIdentifier, lcdWidth, lcdHeight, lcdDensity, env, logger, }: {
25
25
  deviceName: AndroidVirtualDeviceName;
26
26
  systemImagePackage: string;
27
27
  deviceIdentifier: AndroidDeviceName | null;
28
+ lcdWidth: number | null;
29
+ lcdHeight: number | null;
30
+ lcdDensity: number | null;
28
31
  env: NodeJS.ProcessEnv;
29
32
  logger: bunyan;
30
33
  }): Promise<void>;
@@ -68,7 +68,7 @@ var AndroidEmulatorUtils;
68
68
  return null;
69
69
  }
70
70
  AndroidEmulatorUtils.getSerialIdAsync = getSerialIdAsync;
71
- async function createAsync({ deviceName, systemImagePackage, deviceIdentifier, env, logger, }) {
71
+ async function createAsync({ deviceName, systemImagePackage, deviceIdentifier, lcdWidth, lcdHeight, lcdDensity, env, logger, }) {
72
72
  const avdManager = (0, turtle_spawn_1.default)('avdmanager', [
73
73
  'create',
74
74
  'avd',
@@ -121,6 +121,10 @@ var AndroidEmulatorUtils;
121
121
  }
122
122
  }
123
123
  }
124
+ if (lcdWidth !== null && lcdHeight !== null && lcdDensity !== null) {
125
+ logger.info(`Setting screen resolution to ${lcdWidth}x${lcdHeight} and density to ${lcdDensity} ppi.`);
126
+ configIniFileContent = `${configIniFileContent}\nhw.lcd.height=${lcdHeight}\nhw.lcd.width=${lcdWidth}\nhw.lcd.density=${lcdDensity}\n`;
127
+ }
124
128
  const shouldAdjustHeapSize = env.ANDROID_EMULATOR_ADJUST_HEAP_SIZE !== 'false' &&
125
129
  env.ANDROID_EMULATOR_ADJUST_HEAP_SIZE !== '0';
126
130
  if (shouldAdjustHeapSize) {
@@ -0,0 +1,2 @@
1
+ import { type bunyan } from '@expo/logger';
2
+ export declare function withLogPhaseAsync<T>(logger: bunyan, name: string, fn: (logger: bunyan) => Promise<T>): Promise<T>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withLogPhaseAsync = withLogPhaseAsync;
4
+ const eas_build_job_1 = require("@expo/eas-build-job");
5
+ const steps_1 = require("@expo/steps");
6
+ async function withLogPhaseAsync(logger, name, fn) {
7
+ const phaseLogger = logger.child({
8
+ phase: eas_build_job_1.BuildPhase.CUSTOM,
9
+ buildStepId: steps_1.BuildStep.getNewId(),
10
+ buildStepDisplayName: name,
11
+ });
12
+ phaseLogger.info({ marker: eas_build_job_1.LogMarker.START_PHASE }, `Start phase: ${name}`);
13
+ try {
14
+ const result = await fn(phaseLogger);
15
+ phaseLogger.info({ marker: eas_build_job_1.LogMarker.END_PHASE, result: eas_build_job_1.BuildPhaseResult.SUCCESS }, `End phase: ${name}`);
16
+ return result;
17
+ }
18
+ catch (error) {
19
+ phaseLogger.info({ marker: eas_build_job_1.LogMarker.END_PHASE, result: eas_build_job_1.BuildPhaseResult.FAIL }, `End phase: ${name}`);
20
+ throw error;
21
+ }
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "23.2.0",
3
+ "version": "24.1.0",
4
4
  "bugs": "https://github.com/expo/eas-cli/issues",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Expo <support@expo.io>",
@@ -39,17 +39,17 @@
39
39
  "dependencies": {
40
40
  "@expo/config": "55.0.10",
41
41
  "@expo/config-plugins": "55.0.7",
42
- "@expo/downloader": "23.0.0",
43
- "@expo/eas-build-job": "23.1.0",
42
+ "@expo/downloader": "24.0.0",
43
+ "@expo/eas-build-job": "24.0.0",
44
44
  "@expo/env": "^0.4.0",
45
- "@expo/logger": "23.1.0",
45
+ "@expo/logger": "24.0.0",
46
46
  "@expo/package-manager": "1.9.10",
47
47
  "@expo/plist": "^0.3.5",
48
48
  "@expo/results": "^1.0.0",
49
49
  "@expo/spawn-async": "1.7.2",
50
- "@expo/steps": "23.1.0",
51
- "@expo/template-file": "23.0.0",
52
- "@expo/turtle-spawn": "23.1.0",
50
+ "@expo/steps": "24.0.0",
51
+ "@expo/template-file": "24.0.0",
52
+ "@expo/turtle-spawn": "24.0.0",
53
53
  "@expo/xcpretty": "^4.3.1",
54
54
  "@ngrok/ngrok": "1.7.0",
55
55
  "@sentry/node": "7.77.0",
@@ -102,5 +102,5 @@
102
102
  "typescript": "^5.5.4",
103
103
  "uuid": "^9.0.1"
104
104
  },
105
- "gitHead": "74292d2ace404759ab8936d5aa1369e15d4b4f9d"
105
+ "gitHead": "8373ae353ca615ba2170eac2399f7592ad72d36a"
106
106
  }