@expo/build-tools 1.0.202 → 1.0.204

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.
@@ -22,7 +22,13 @@ function createInstallMaestroBuildFunction() {
22
22
  allowedValueTypeName: steps_1.BuildStepInputValueTypeName.STRING,
23
23
  }),
24
24
  ],
25
- fn: async ({ logger, global }, { inputs, env }) => {
25
+ outputProviders: [
26
+ steps_1.BuildStepOutput.createProvider({
27
+ id: 'maestro_version',
28
+ required: false,
29
+ }),
30
+ ],
31
+ fn: async ({ logger, global }, { inputs, env, outputs }) => {
26
32
  const requestedMaestroVersion = inputs.maestro_version.value;
27
33
  const currentMaestroVersion = await getMaestroVersion({ env });
28
34
  // When not running in EAS Build VM, do not modify local environment.
@@ -46,6 +52,7 @@ function createInstallMaestroBuildFunction() {
46
52
  logger.warn('For more info, check out Maestro installation guide: https://maestro.mobile.dev/getting-started/installing-maestro');
47
53
  }
48
54
  if (currentMaestroVersion) {
55
+ outputs.maestro_version.set(currentMaestroVersion);
49
56
  logger.info(`Maestro ${currentMaestroVersion} is ready.`);
50
57
  }
51
58
  return;
@@ -70,7 +77,8 @@ function createInstallMaestroBuildFunction() {
70
77
  }
71
78
  // Skip installing if the input sets a specific Maestro version to install
72
79
  // and it is already installed which happens when developing on a local computer.
73
- if (!currentMaestroVersion || requestedMaestroVersion !== currentMaestroVersion) {
80
+ if (!currentMaestroVersion ||
81
+ (requestedMaestroVersion && requestedMaestroVersion !== currentMaestroVersion)) {
74
82
  await installMaestro({
75
83
  version: requestedMaestroVersion,
76
84
  global,
@@ -81,6 +89,7 @@ function createInstallMaestroBuildFunction() {
81
89
  const maestroVersion = await getMaestroVersion({ env });
82
90
  (0, assert_1.default)(maestroVersion, 'Failed to ensure Maestro is installed.');
83
91
  logger.info(`Maestro ${maestroVersion} is ready.`);
92
+ outputs.maestro_version.set(maestroVersion);
84
93
  },
85
94
  });
86
95
  }
@@ -112,7 +121,9 @@ async function installMaestro({ global, version, logger, env, }) {
112
121
  env: {
113
122
  ...env,
114
123
  MAESTRO_DIR: maestroDir,
115
- MAESTRO_VERSION: version,
124
+ // _Not_ providing MAESTRO_VERSION installs latest.
125
+ // MAESTRO_VERSION is used to interpolate the download URL like github.com/releases/cli-$MAESTRO_VERSION...
126
+ MAESTRO_VERSION: version === 'latest' ? undefined : version,
116
127
  },
117
128
  });
118
129
  // That's where Maestro installs binary as of February 2024
@@ -1 +1 @@
1
- {"version":3,"file":"installMaestro.js","sourceRoot":"","sources":["../../../src/steps/functions/installMaestro.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport {\n BuildFunction,\n BuildRuntimePlatform,\n BuildStepEnv,\n BuildStepGlobalContext,\n BuildStepInput,\n BuildStepInputValueTypeName,\n} from '@expo/steps';\nimport spawn from '@expo/turtle-spawn';\nimport { bunyan } from '@expo/logger';\n\nexport function createInstallMaestroBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'install_maestro',\n name: 'Install Maestro',\n inputProviders: [\n BuildStepInput.createProvider({\n id: 'maestro_version',\n required: false,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n ],\n fn: async ({ logger, global }, { inputs, env }) => {\n const requestedMaestroVersion = inputs.maestro_version.value as string | undefined;\n const currentMaestroVersion = await getMaestroVersion({ env });\n\n // When not running in EAS Build VM, do not modify local environment.\n if (env.EAS_BUILD_RUNNER !== 'eas-build') {\n const currentIsJavaInstalled = await isJavaInstalled({ env });\n const currentIsIdbInstalled = await isIdbInstalled({ env });\n\n if (!currentIsJavaInstalled) {\n logger.warn(\n 'It seems Java is not installed. It is required to run Maestro. If the job fails, this may be the reason.'\n );\n logger.info('');\n }\n\n if (!currentIsIdbInstalled) {\n logger.warn(\n 'It seems IDB is not installed. Maestro requires it to run flows on iOS Simulator. If the job fails, this may be the reason.'\n );\n logger.info('');\n }\n\n if (!currentMaestroVersion) {\n logger.warn(\n 'It seems Maestro is not installed. Please install Maestro manually and rerun the job.'\n );\n logger.info('');\n }\n\n // Guide is helpful in these two cases, it doesn't mention Java.\n if (!currentIsIdbInstalled || !currentMaestroVersion) {\n logger.warn(\n 'For more info, check out Maestro installation guide: https://maestro.mobile.dev/getting-started/installing-maestro'\n );\n }\n\n if (currentMaestroVersion) {\n logger.info(`Maestro ${currentMaestroVersion} is ready.`);\n }\n\n return;\n }\n\n if (!(await isJavaInstalled({ env }))) {\n if (global.runtimePlatform === BuildRuntimePlatform.DARWIN) {\n logger.info('Installing Java');\n await installJavaFromGcs({ logger, env });\n } else {\n // We expect Java to be pre-installed on Linux images,\n // so this should only happen when running this step locally.\n // We don't need to support installing Java on local computers.\n throw new Error('Please install Java manually and rerun the job.');\n }\n }\n\n // IDB is only a requirement on macOS.\n if (\n global.runtimePlatform === BuildRuntimePlatform.DARWIN &&\n !(await isIdbInstalled({ env }))\n ) {\n logger.info('Installing IDB');\n await installIdbFromBrew({ logger, env });\n }\n\n // Skip installing if the input sets a specific Maestro version to install\n // and it is already installed which happens when developing on a local computer.\n if (!currentMaestroVersion || requestedMaestroVersion !== currentMaestroVersion) {\n await installMaestro({\n version: requestedMaestroVersion,\n global,\n logger,\n env,\n });\n }\n\n const maestroVersion = await getMaestroVersion({ env });\n assert(maestroVersion, 'Failed to ensure Maestro is installed.');\n logger.info(`Maestro ${maestroVersion} is ready.`);\n },\n });\n}\n\nasync function getMaestroVersion({ env }: { env: BuildStepEnv }): Promise<string | null> {\n try {\n const maestroVersion = await spawn('maestro', ['--version'], { stdio: 'pipe', env });\n return maestroVersion.stdout.trim();\n } catch {\n return null;\n }\n}\n\nasync function installMaestro({\n global,\n version,\n logger,\n env,\n}: {\n version?: string;\n logger: bunyan;\n global: BuildStepGlobalContext;\n env: BuildStepEnv;\n}): Promise<void> {\n logger.info('Fetching install script');\n const tempDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'install_maestro'));\n try {\n const installMaestroScriptResponse = await fetch('https://get.maestro.mobile.dev');\n const installMaestroScript = await installMaestroScriptResponse.text();\n const installMaestroScriptFilePath = path.join(tempDirectory, 'install_maestro.sh');\n await fs.promises.writeFile(installMaestroScriptFilePath, installMaestroScript, {\n mode: 0o777,\n });\n logger.info('Installing Maestro');\n assert(\n env.HOME,\n 'Failed to infer directory to install Maestro in: $HOME environment variable is empty.'\n );\n const maestroDir = path.join(env.HOME, '.maestro');\n await spawn(installMaestroScriptFilePath, [], {\n logger,\n env: {\n ...env,\n MAESTRO_DIR: maestroDir,\n MAESTRO_VERSION: version,\n },\n });\n // That's where Maestro installs binary as of February 2024\n // I suspect/hope they don't change the location.\n const maestroBinDir = path.join(maestroDir, 'bin');\n global.updateEnv({\n ...global.env,\n PATH: `${global.env.PATH}:${maestroBinDir}`,\n });\n env.PATH = `${env.PATH}:${maestroBinDir}`;\n process.env.PATH = `${process.env.PATH}:${maestroBinDir}`;\n } finally {\n await fs.promises.rm(tempDirectory, { force: true, recursive: true });\n }\n}\n\nasync function isIdbInstalled({ env }: { env: BuildStepEnv }): Promise<boolean> {\n try {\n await spawn('idb', ['-h'], { ignoreStdio: true, env });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function installIdbFromBrew({\n logger,\n env,\n}: {\n logger: bunyan;\n env: BuildStepEnv;\n}): Promise<void> {\n // Unfortunately our Mac images sometimes have two Homebrew\n // installations. We should use the ARM64 one, located in /opt/homebrew.\n const brewPath = '/opt/homebrew/bin/brew';\n const localEnv = {\n ...env,\n HOMEBREW_NO_AUTO_UPDATE: '1',\n HOMEBREW_NO_INSTALL_CLEANUP: '1',\n };\n\n await spawn(brewPath, ['tap', 'facebook/fb'], {\n env: localEnv,\n logger,\n });\n await spawn(brewPath, ['install', 'idb-companion'], {\n env: localEnv,\n logger,\n });\n}\n\nasync function isJavaInstalled({ env }: { env: BuildStepEnv }): Promise<boolean> {\n try {\n await spawn('java', ['-version'], { ignoreStdio: true, env });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Installs Java 11 from a file uploaded manually to GCS as cache.\n * Should not be run outside of EAS Build VMs not to break users' environments.\n */\nasync function installJavaFromGcs({\n logger,\n env,\n}: {\n logger: bunyan;\n env: BuildStepEnv;\n}): Promise<void> {\n const downloadUrl =\n 'https://storage.googleapis.com/turtle-v2/zulu11.68.17-ca-jdk11.0.21-macosx_aarch64.dmg';\n const filename = path.basename(downloadUrl);\n const tempDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'install_java'));\n const installerPath = path.join(tempDirectory, filename);\n const installerMountDirectory = path.join(tempDirectory, 'mountpoint');\n try {\n logger.info('Downloading Java installer');\n // This is simpler than piping body into a write stream with node-fetch.\n await spawn('curl', ['--output', installerPath, downloadUrl], { env });\n\n await fs.promises.mkdir(installerMountDirectory);\n logger.info('Mounting Java installer');\n await spawn(\n 'hdiutil',\n ['attach', installerPath, '-noverify', '-mountpoint', installerMountDirectory],\n { env }\n );\n\n logger.info('Installing Java');\n await spawn(\n 'sudo',\n [\n 'installer',\n '-pkg',\n path.join(installerMountDirectory, 'Double-Click to Install Azul Zulu JDK 11.pkg'),\n '-target',\n '/',\n ],\n { env }\n );\n } finally {\n try {\n // We need to unmount to remove, otherwise we get \"resource busy\"\n await spawn('hdiutil', ['detach', installerMountDirectory], { env });\n } catch {}\n\n await fs.promises.rm(tempDirectory, { force: true, recursive: true });\n }\n}\n"]}
1
+ {"version":3,"file":"installMaestro.js","sourceRoot":"","sources":["../../../src/steps/functions/installMaestro.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport {\n BuildFunction,\n BuildRuntimePlatform,\n BuildStepEnv,\n BuildStepGlobalContext,\n BuildStepInput,\n BuildStepInputValueTypeName,\n BuildStepOutput,\n} from '@expo/steps';\nimport spawn from '@expo/turtle-spawn';\nimport { bunyan } from '@expo/logger';\n\nexport function createInstallMaestroBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'install_maestro',\n name: 'Install Maestro',\n inputProviders: [\n BuildStepInput.createProvider({\n id: 'maestro_version',\n required: false,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n ],\n outputProviders: [\n BuildStepOutput.createProvider({\n id: 'maestro_version',\n required: false,\n }),\n ],\n fn: async ({ logger, global }, { inputs, env, outputs }) => {\n const requestedMaestroVersion = inputs.maestro_version.value as string | undefined;\n const currentMaestroVersion = await getMaestroVersion({ env });\n\n // When not running in EAS Build VM, do not modify local environment.\n if (env.EAS_BUILD_RUNNER !== 'eas-build') {\n const currentIsJavaInstalled = await isJavaInstalled({ env });\n const currentIsIdbInstalled = await isIdbInstalled({ env });\n\n if (!currentIsJavaInstalled) {\n logger.warn(\n 'It seems Java is not installed. It is required to run Maestro. If the job fails, this may be the reason.'\n );\n logger.info('');\n }\n\n if (!currentIsIdbInstalled) {\n logger.warn(\n 'It seems IDB is not installed. Maestro requires it to run flows on iOS Simulator. If the job fails, this may be the reason.'\n );\n logger.info('');\n }\n\n if (!currentMaestroVersion) {\n logger.warn(\n 'It seems Maestro is not installed. Please install Maestro manually and rerun the job.'\n );\n logger.info('');\n }\n\n // Guide is helpful in these two cases, it doesn't mention Java.\n if (!currentIsIdbInstalled || !currentMaestroVersion) {\n logger.warn(\n 'For more info, check out Maestro installation guide: https://maestro.mobile.dev/getting-started/installing-maestro'\n );\n }\n\n if (currentMaestroVersion) {\n outputs.maestro_version.set(currentMaestroVersion);\n logger.info(`Maestro ${currentMaestroVersion} is ready.`);\n }\n\n return;\n }\n\n if (!(await isJavaInstalled({ env }))) {\n if (global.runtimePlatform === BuildRuntimePlatform.DARWIN) {\n logger.info('Installing Java');\n await installJavaFromGcs({ logger, env });\n } else {\n // We expect Java to be pre-installed on Linux images,\n // so this should only happen when running this step locally.\n // We don't need to support installing Java on local computers.\n throw new Error('Please install Java manually and rerun the job.');\n }\n }\n\n // IDB is only a requirement on macOS.\n if (\n global.runtimePlatform === BuildRuntimePlatform.DARWIN &&\n !(await isIdbInstalled({ env }))\n ) {\n logger.info('Installing IDB');\n await installIdbFromBrew({ logger, env });\n }\n\n // Skip installing if the input sets a specific Maestro version to install\n // and it is already installed which happens when developing on a local computer.\n if (\n !currentMaestroVersion ||\n (requestedMaestroVersion && requestedMaestroVersion !== currentMaestroVersion)\n ) {\n await installMaestro({\n version: requestedMaestroVersion,\n global,\n logger,\n env,\n });\n }\n\n const maestroVersion = await getMaestroVersion({ env });\n assert(maestroVersion, 'Failed to ensure Maestro is installed.');\n logger.info(`Maestro ${maestroVersion} is ready.`);\n outputs.maestro_version.set(maestroVersion);\n },\n });\n}\n\nasync function getMaestroVersion({ env }: { env: BuildStepEnv }): Promise<string | null> {\n try {\n const maestroVersion = await spawn('maestro', ['--version'], { stdio: 'pipe', env });\n return maestroVersion.stdout.trim();\n } catch {\n return null;\n }\n}\n\nasync function installMaestro({\n global,\n version,\n logger,\n env,\n}: {\n version?: string;\n logger: bunyan;\n global: BuildStepGlobalContext;\n env: BuildStepEnv;\n}): Promise<void> {\n logger.info('Fetching install script');\n const tempDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'install_maestro'));\n try {\n const installMaestroScriptResponse = await fetch('https://get.maestro.mobile.dev');\n const installMaestroScript = await installMaestroScriptResponse.text();\n const installMaestroScriptFilePath = path.join(tempDirectory, 'install_maestro.sh');\n await fs.promises.writeFile(installMaestroScriptFilePath, installMaestroScript, {\n mode: 0o777,\n });\n logger.info('Installing Maestro');\n assert(\n env.HOME,\n 'Failed to infer directory to install Maestro in: $HOME environment variable is empty.'\n );\n const maestroDir = path.join(env.HOME, '.maestro');\n await spawn(installMaestroScriptFilePath, [], {\n logger,\n env: {\n ...env,\n MAESTRO_DIR: maestroDir,\n // _Not_ providing MAESTRO_VERSION installs latest.\n // MAESTRO_VERSION is used to interpolate the download URL like github.com/releases/cli-$MAESTRO_VERSION...\n MAESTRO_VERSION: version === 'latest' ? undefined : version,\n },\n });\n // That's where Maestro installs binary as of February 2024\n // I suspect/hope they don't change the location.\n const maestroBinDir = path.join(maestroDir, 'bin');\n global.updateEnv({\n ...global.env,\n PATH: `${global.env.PATH}:${maestroBinDir}`,\n });\n env.PATH = `${env.PATH}:${maestroBinDir}`;\n process.env.PATH = `${process.env.PATH}:${maestroBinDir}`;\n } finally {\n await fs.promises.rm(tempDirectory, { force: true, recursive: true });\n }\n}\n\nasync function isIdbInstalled({ env }: { env: BuildStepEnv }): Promise<boolean> {\n try {\n await spawn('idb', ['-h'], { ignoreStdio: true, env });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function installIdbFromBrew({\n logger,\n env,\n}: {\n logger: bunyan;\n env: BuildStepEnv;\n}): Promise<void> {\n // Unfortunately our Mac images sometimes have two Homebrew\n // installations. We should use the ARM64 one, located in /opt/homebrew.\n const brewPath = '/opt/homebrew/bin/brew';\n const localEnv = {\n ...env,\n HOMEBREW_NO_AUTO_UPDATE: '1',\n HOMEBREW_NO_INSTALL_CLEANUP: '1',\n };\n\n await spawn(brewPath, ['tap', 'facebook/fb'], {\n env: localEnv,\n logger,\n });\n await spawn(brewPath, ['install', 'idb-companion'], {\n env: localEnv,\n logger,\n });\n}\n\nasync function isJavaInstalled({ env }: { env: BuildStepEnv }): Promise<boolean> {\n try {\n await spawn('java', ['-version'], { ignoreStdio: true, env });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Installs Java 11 from a file uploaded manually to GCS as cache.\n * Should not be run outside of EAS Build VMs not to break users' environments.\n */\nasync function installJavaFromGcs({\n logger,\n env,\n}: {\n logger: bunyan;\n env: BuildStepEnv;\n}): Promise<void> {\n const downloadUrl =\n 'https://storage.googleapis.com/turtle-v2/zulu11.68.17-ca-jdk11.0.21-macosx_aarch64.dmg';\n const filename = path.basename(downloadUrl);\n const tempDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'install_java'));\n const installerPath = path.join(tempDirectory, filename);\n const installerMountDirectory = path.join(tempDirectory, 'mountpoint');\n try {\n logger.info('Downloading Java installer');\n // This is simpler than piping body into a write stream with node-fetch.\n await spawn('curl', ['--output', installerPath, downloadUrl], { env });\n\n await fs.promises.mkdir(installerMountDirectory);\n logger.info('Mounting Java installer');\n await spawn(\n 'hdiutil',\n ['attach', installerPath, '-noverify', '-mountpoint', installerMountDirectory],\n { env }\n );\n\n logger.info('Installing Java');\n await spawn(\n 'sudo',\n [\n 'installer',\n '-pkg',\n path.join(installerMountDirectory, 'Double-Click to Install Azul Zulu JDK 11.pkg'),\n '-target',\n '/',\n ],\n { env }\n );\n } finally {\n try {\n // We need to unmount to remove, otherwise we get \"resource busy\"\n await spawn('hdiutil', ['detach', installerMountDirectory], { env });\n } catch {}\n\n await fs.promises.rm(tempDirectory, { force: true, recursive: true });\n }\n}\n"]}
@@ -7,6 +7,7 @@ exports.getMaestroTestCommand = exports.createInternalEasMaestroTestFunction = v
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const node_os_1 = __importDefault(require("node:os"));
10
+ const promises_1 = require("node:timers/promises");
10
11
  const steps_1 = require("@expo/steps");
11
12
  const zod_1 = require("zod");
12
13
  const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
@@ -148,6 +149,8 @@ function createInternalEasMaestroTestFunction(ctx) {
148
149
  await (0, steps_1.spawnAsync)('adb', ['-s', serialId, 'emu', 'kill'], {
149
150
  stdio: 'pipe',
150
151
  });
152
+ // Waiting for emulator to get killed, see ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL.
153
+ await (0, promises_1.setTimeout)(1000);
151
154
  sourceDeviceIdentifier = avdName;
152
155
  break;
153
156
  }
@@ -231,7 +234,7 @@ function createInternalEasMaestroTestFunction(ctx) {
231
234
  logger: stepCtx.logger,
232
235
  artifact: {
233
236
  // TODO(sjchmiela): Add metadata to artifacts so we don't need to encode flow path and attempt in the name.
234
- name: `Screen Recording (${flowPath})`,
237
+ name: `Screen Recording (${flowIndex}-${node_path_1.default.basename(flowPath, node_path_1.default.extname(flowPath))})`,
235
238
  paths: [recordingResult.value],
236
239
  type: eas_build_job_1.GenericArtifactType.OTHER,
237
240
  },
@@ -1 +1 @@
1
- {"version":3,"file":"internalMaestroTest.js","sourceRoot":"","sources":["../../../src/steps/functions/internalMaestroTest.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nimport {\n BuildFunction,\n BuildStepEnv,\n BuildStepInput,\n BuildStepInputValueTypeName,\n spawnAsync,\n} from '@expo/steps';\nimport { z } from 'zod';\nimport spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';\nimport { PipeMode, bunyan } from '@expo/logger';\nimport { Result, asyncResult, result } from '@expo/results';\nimport { GenericArtifactType } from '@expo/eas-build-job';\n\nimport { CustomBuildContext } from '../../customBuildContext';\nimport { IosSimulatorName, IosSimulatorUtils } from '../../utils/IosSimulatorUtils';\nimport {\n AndroidDeviceSerialId,\n AndroidEmulatorUtils,\n AndroidVirtualDeviceName,\n} from '../../utils/AndroidEmulatorUtils';\nimport { PlatformToProperNounMap } from '../../utils/strings';\nimport { findMaestroPathsFlowsToExecuteAsync } from '../../utils/findMaestroPathsFlowsToExecuteAsync';\n\nexport function createInternalEasMaestroTestFunction(ctx: CustomBuildContext): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: '__maestro_test',\n inputProviders: [\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'platform',\n required: true,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.JSON,\n id: 'flow_paths',\n required: true,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n id: 'retries',\n defaultValue: 1,\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'include_tags',\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'exclude_tags',\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n id: 'shards',\n defaultValue: 1,\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'output_format',\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.BOOLEAN,\n id: 'record_screen',\n defaultValue: false,\n required: false,\n }),\n ],\n fn: async (stepCtx, { inputs: _inputs, env }) => {\n // inputs come in form of { value: unknown }. Here we parse them into a typed and validated object.\n const {\n platform,\n flow_paths,\n retries,\n include_tags,\n exclude_tags,\n shards,\n output_format,\n record_screen,\n } = z\n .object({\n platform: z.enum(['ios', 'android']),\n flow_paths: z.array(z.string()),\n retries: z.number().default(1),\n include_tags: z.string().optional(),\n exclude_tags: z.string().optional(),\n shards: z.number().default(1),\n output_format: z.string().optional(),\n record_screen: z.boolean().default(false),\n })\n .parse(\n Object.fromEntries(Object.entries(_inputs).map(([key, value]) => [key, value.value]))\n );\n\n const flowPathsToExecute: string[] = [];\n for (const flowPath of flow_paths) {\n const flowPaths = await findMaestroPathsFlowsToExecuteAsync({\n workingDirectory: stepCtx.workingDirectory,\n flowPath,\n logger: stepCtx.logger,\n includeTags: include_tags ? include_tags.split(',') : undefined,\n excludeTags: exclude_tags ? exclude_tags.split(',') : undefined,\n });\n if (flowPaths.length === 0) {\n stepCtx.logger.warn(`No flows to execute found in \"${flowPath}\".`);\n continue;\n }\n stepCtx.logger.info(\n `Marking for execution:\\n- ${flowPaths.map((flowPath) => path.relative(stepCtx.workingDirectory, flowPath)).join('\\n- ')}`\n );\n stepCtx.logger.info('');\n flowPathsToExecute.push(...flowPaths);\n }\n\n // TODO: Add support for shards. (Shouldn't be too difficult.)\n if (shards > 1) {\n stepCtx.logger.warn(\n 'Sharding support has been temporarily disabled. Running tests on a single shard.'\n );\n }\n\n // eas/__maestro_test does not start devices, it expects a single device to be already running\n // and configured with the app. Here we find the booted device and stop it.\n\n let sourceDeviceIdentifier: IosSimulatorName | AndroidVirtualDeviceName;\n\n switch (platform) {\n case 'ios': {\n const bootedDevices = await IosSimulatorUtils.getAvailableDevicesAsync({\n env,\n filter: 'booted',\n });\n if (bootedDevices.length === 0) {\n throw new Error('No booted iOS Simulator found.');\n } else if (bootedDevices.length > 1) {\n throw new Error('Multiple booted iOS Simulators found.');\n }\n\n const device = bootedDevices[0];\n stepCtx.logger.info(`Running tests on iOS Simulator: ${device.name}.`);\n\n stepCtx.logger.info(`Preparing Simulator for tests...`);\n await spawnAsync('xcrun', ['simctl', 'shutdown', device.udid], {\n logger: stepCtx.logger,\n stdio: 'pipe',\n });\n\n sourceDeviceIdentifier = device.name;\n break;\n }\n case 'android': {\n const connectedDevices = await AndroidEmulatorUtils.getAttachedDevicesAsync({ env });\n if (connectedDevices.length === 0) {\n throw new Error('No booted Android Emulator found.');\n } else if (connectedDevices.length > 1) {\n throw new Error('Multiple booted Android Emulators found.');\n }\n\n const { serialId } = connectedDevices[0];\n const adbEmuAvdNameResult = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n mode: PipeMode.COMBINED,\n env,\n });\n const avdName = adbEmuAvdNameResult.stdout\n .replace(/\\r\\n/g, '\\n')\n .split('\\n')[0] as AndroidVirtualDeviceName;\n stepCtx.logger.info(`Running tests on Android Emulator: ${avdName}.`);\n\n stepCtx.logger.info(`Preparing Emulator for tests...`);\n await spawnAsync('adb', ['-s', serialId, 'emu', 'kill'], {\n stdio: 'pipe',\n });\n\n sourceDeviceIdentifier = avdName;\n break;\n }\n }\n\n // During tests we generate reports and device logs. We store them in temporary directories\n // and upload them once all tests are done. When a test is retried, new reports overwrite\n // the old ones. The files are named \"flow-${index}\" for easier identification.\n const maestroReportsDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), 'maestro-reports-')\n );\n const deviceLogsDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'device-logs-'));\n\n const failedFlows: string[] = [];\n\n for (const [flowIndex, flowPath] of flowPathsToExecute.entries()) {\n stepCtx.logger.info('');\n\n // If output_format is empty or noop, we won't use this.\n const outputPath = path.join(\n maestroReportsDir,\n [\n `${output_format + '-' ?? ''}report-flow-${flowIndex + 1}`,\n MaestroOutputFormatToExtensionMap[output_format ?? 'noop'],\n ]\n .filter(Boolean)\n .join('.')\n );\n\n for (let attemptCount = 0; attemptCount < retries; attemptCount++) {\n const localDeviceName = `eas-simulator-${flowIndex}-${attemptCount}` as\n | IosSimulatorName\n | AndroidVirtualDeviceName;\n\n // If the test passes, but the recording fails, we don't want to make the test fail,\n // so we return two separate results.\n const {\n fnResult: { fnResult, recordingResult },\n logsResult,\n } = await withCleanDeviceAsync({\n platform,\n sourceDeviceIdentifier,\n localDeviceName,\n env,\n logger: stepCtx.logger,\n fn: async ({ deviceIdentifier }) => {\n return await maybeWithScreenRecordingAsync({\n shouldRecord: record_screen,\n platform,\n deviceIdentifier,\n env,\n logger: stepCtx.logger,\n fn: async () => {\n stepCtx.logger.info('');\n\n const [command, ...args] = getMaestroTestCommand({\n flow_path: flowPath,\n output_format,\n output_path: outputPath,\n });\n\n try {\n await spawnAsync(command, args, {\n logger: stepCtx.logger,\n cwd: stepCtx.workingDirectory,\n env,\n stdio: 'pipe',\n });\n } finally {\n stepCtx.logger.info('');\n }\n },\n });\n },\n });\n\n // Move device logs to the device logs directory.\n if (logsResult?.ok) {\n try {\n const extension = path.extname(logsResult.value.outputPath);\n const destinationPath = path.join(deviceLogsDir, `flow-${flowIndex}${extension}`);\n\n await fs.promises.rm(destinationPath, {\n force: true,\n recursive: true,\n });\n await fs.promises.rename(logsResult.value.outputPath, destinationPath);\n } catch (err) {\n stepCtx.logger.warn({ err }, 'Failed to prepare device logs for upload.');\n }\n } else if (logsResult?.reason) {\n stepCtx.logger.error({ err: logsResult.reason }, 'Failed to collect device logs.');\n }\n\n const isLastAttempt = fnResult.ok || attemptCount === retries - 1;\n if (isLastAttempt && recordingResult.value) {\n try {\n await ctx.runtimeApi.uploadArtifact({\n logger: stepCtx.logger,\n artifact: {\n // TODO(sjchmiela): Add metadata to artifacts so we don't need to encode flow path and attempt in the name.\n name: `Screen Recording (${flowPath})`,\n paths: [recordingResult.value],\n type: GenericArtifactType.OTHER,\n },\n });\n } catch (err) {\n stepCtx.logger.warn({ err }, 'Failed to upload screen recording.');\n }\n }\n\n if (fnResult.ok) {\n stepCtx.logger.info(`Test passed.`);\n // Break out of the retry loop.\n break;\n }\n\n if (attemptCount < retries - 1) {\n stepCtx.logger.info(`Retrying test...`);\n stepCtx.logger.info('');\n continue;\n }\n\n // fnResult.reason is not super interesting, but it does print out the full command so we can keep it for debugging purposes.\n stepCtx.logger.error({ err: fnResult.reason }, 'Test errored.');\n failedFlows.push(flowPath);\n }\n }\n\n stepCtx.logger.info('');\n\n // When all tests are done, we upload the reports and device logs.\n const generatedMaestroReports = await fs.promises.readdir(maestroReportsDir);\n if (generatedMaestroReports.length === 0) {\n stepCtx.logger.warn('No reports were generated.');\n } else {\n stepCtx.logger.info(`Uploading reports...`);\n try {\n await ctx.runtimeApi.uploadArtifact({\n logger: stepCtx.logger,\n artifact: {\n name: `${PlatformToProperNounMap[platform]} Maestro Test Reports (${output_format})`,\n paths: [maestroReportsDir],\n type: GenericArtifactType.OTHER,\n },\n });\n } catch (err) {\n stepCtx.logger.error({ err }, 'Failed to upload reports.');\n }\n }\n\n const generatedDeviceLogs = await fs.promises.readdir(deviceLogsDir);\n if (generatedDeviceLogs.length === 0) {\n stepCtx.logger.warn('No device logs were successfully collected.');\n } else {\n stepCtx.logger.info(`Uploading device logs...`);\n try {\n await ctx.runtimeApi.uploadArtifact({\n logger: stepCtx.logger,\n artifact: {\n name: `Maestro Test Device Logs`,\n paths: [deviceLogsDir],\n type: GenericArtifactType.OTHER,\n },\n });\n } catch (err) {\n stepCtx.logger.error({ err }, 'Failed to upload device logs.');\n }\n }\n\n stepCtx.logger.info('');\n\n // If any tests failed, we throw an error to mark the step as failed.\n if (failedFlows.length > 0) {\n throw new Error(\n `Some Maestro tests failed:\\n- ${failedFlows\n .map((flowPath) => path.relative(stepCtx.workingDirectory, flowPath))\n .join('\\n- ')}`\n );\n } else {\n stepCtx.logger.info('All Maestro tests passed.');\n }\n },\n });\n}\n\nexport function getMaestroTestCommand(params: {\n flow_path: string;\n output_format: string | undefined;\n /** Unused if `output_format` is undefined */\n output_path: string;\n}): [command: string, ...args: string[]] {\n let outputFormatFlags: string[] = [];\n if (params.output_format) {\n outputFormatFlags = [`--format`, params.output_format, `--output`, params.output_path];\n }\n\n return ['maestro', 'test', ...outputFormatFlags, params.flow_path] as [\n command: string,\n ...args: string[],\n ];\n}\n\nconst MaestroOutputFormatToExtensionMap: Record<string, string | undefined> = {\n junit: 'xml',\n html: 'html',\n};\n\nasync function withCleanDeviceAsync<TResult>({\n platform,\n sourceDeviceIdentifier,\n localDeviceName,\n env,\n logger,\n fn,\n}: {\n env: BuildStepEnv;\n logger: bunyan;\n platform: 'ios' | 'android';\n sourceDeviceIdentifier: IosSimulatorName | AndroidVirtualDeviceName;\n localDeviceName: IosSimulatorName | AndroidVirtualDeviceName;\n fn: ({\n deviceIdentifier,\n }: {\n deviceIdentifier: IosSimulatorName | AndroidDeviceSerialId;\n }) => Promise<TResult>;\n}): Promise<{ fnResult: TResult; logsResult: Result<{ outputPath: string }> | null }> {\n // Clone and start the device\n\n let localDeviceIdentifier: IosSimulatorName | AndroidDeviceSerialId;\n\n switch (platform) {\n case 'ios': {\n logger.info(`Cloning iOS Simulator ${sourceDeviceIdentifier} to ${localDeviceName}...`);\n await IosSimulatorUtils.cloneAsync({\n sourceDeviceIdentifier: sourceDeviceIdentifier as IosSimulatorName,\n destinationDeviceName: localDeviceName as IosSimulatorName,\n env,\n });\n logger.info(`Starting iOS Simulator ${localDeviceName}...`);\n const { udid } = await IosSimulatorUtils.startAsync({\n deviceIdentifier: localDeviceName as IosSimulatorName,\n env,\n });\n logger.info(`Waiting for iOS Simulator ${localDeviceName} to be ready...`);\n await IosSimulatorUtils.waitForReadyAsync({\n udid,\n env,\n });\n localDeviceIdentifier = localDeviceName as IosSimulatorName;\n break;\n }\n case 'android': {\n logger.info(`Cloning Android Emulator ${sourceDeviceIdentifier} to ${localDeviceName}...`);\n await AndroidEmulatorUtils.cloneAsync({\n sourceDeviceName: sourceDeviceIdentifier as AndroidVirtualDeviceName,\n destinationDeviceName: localDeviceName as AndroidVirtualDeviceName,\n env,\n logger,\n });\n logger.info(`Starting Android Emulator ${localDeviceName}...`);\n const { serialId } = await AndroidEmulatorUtils.startAsync({\n deviceName: localDeviceName as AndroidVirtualDeviceName,\n env,\n });\n logger.info(`Waiting for Android Emulator ${localDeviceName} to be ready...`);\n await AndroidEmulatorUtils.waitForReadyAsync({\n serialId,\n env,\n });\n localDeviceIdentifier = serialId;\n break;\n }\n }\n\n // Run the function\n\n const fnResult = await asyncResult(fn({ deviceIdentifier: localDeviceIdentifier }));\n\n // Stop the device\n\n let logsResult: Result<{ outputPath: string }> | null = null;\n\n try {\n switch (platform) {\n case 'ios': {\n logger.info(`Collecting logs from ${localDeviceName}...`);\n logsResult = await asyncResult(\n IosSimulatorUtils.collectLogsAsync({\n deviceIdentifier: localDeviceIdentifier as IosSimulatorName,\n env,\n })\n );\n\n logger.info(`Cleaning up ${localDeviceName}...`);\n await IosSimulatorUtils.deleteAsync({\n deviceIdentifier: localDeviceIdentifier as IosSimulatorName,\n env,\n });\n break;\n }\n case 'android': {\n logger.info(`Collecting logs from ${localDeviceName}...`);\n logsResult = await asyncResult(\n AndroidEmulatorUtils.collectLogsAsync({\n serialId: localDeviceIdentifier as AndroidDeviceSerialId,\n env,\n })\n );\n\n logger.info(`Cleaning up ${localDeviceName}...`);\n await AndroidEmulatorUtils.deleteAsync({\n serialId: localDeviceIdentifier as AndroidDeviceSerialId,\n env,\n });\n break;\n }\n }\n } catch (err) {\n logger.error(`Error cleaning up device: ${err}`);\n }\n\n return { fnResult: fnResult.enforceValue(), logsResult };\n}\n\n/** Runs provided `fn` function, optionally wrapping it with starting and stopping screen recording. */\nasync function maybeWithScreenRecordingAsync<TResult>({\n shouldRecord,\n platform,\n deviceIdentifier,\n env,\n logger,\n fn,\n}: {\n // As weird as it is, it's more convenient to have this function like `maybeWith...`\n // than \"withScreenRecordingAsync\" and `withScreenRecordingAsync(fn)` vs `fn` in the caller.\n shouldRecord: boolean;\n platform: 'ios' | 'android';\n deviceIdentifier: IosSimulatorName | AndroidDeviceSerialId;\n env: BuildStepEnv;\n logger: bunyan;\n fn: () => Promise<TResult>;\n}): Promise<{ fnResult: Result<TResult>; recordingResult: Result<string | null> }> {\n if (!shouldRecord) {\n return { fnResult: await asyncResult(fn()), recordingResult: result(null) };\n }\n\n let recordingResult: Result<{\n recordingSpawn: SpawnPromise<SpawnResult>;\n outputPath?: string;\n }>;\n\n // Start screen recording\n\n logger.info(`Starting screen recording on ${deviceIdentifier}...`);\n\n switch (platform) {\n case 'ios': {\n recordingResult = await asyncResult(\n IosSimulatorUtils.startScreenRecordingAsync({\n deviceIdentifier: deviceIdentifier as IosSimulatorName,\n env,\n })\n );\n break;\n }\n case 'android': {\n recordingResult = await asyncResult(\n AndroidEmulatorUtils.startScreenRecordingAsync({\n serialId: deviceIdentifier as AndroidDeviceSerialId,\n env,\n })\n );\n break;\n }\n }\n\n if (!recordingResult.ok) {\n logger.warn('Failed to start screen recording.', recordingResult.reason);\n }\n\n // Run the function\n\n const fnResult = await asyncResult(fn());\n\n // If recording failed there's nothing to stop, so we return the results\n\n if (!recordingResult.ok) {\n return { fnResult, recordingResult: result(recordingResult.reason) };\n }\n\n // If recording started, finish it\n\n try {\n logger.info(`Stopping screen recording on ${deviceIdentifier}...`);\n\n switch (platform) {\n case 'ios': {\n await IosSimulatorUtils.stopScreenRecordingAsync({\n recordingSpawn: recordingResult.value.recordingSpawn,\n });\n return {\n fnResult,\n // We know outputPath is defined, because startIosScreenRecording() should have filled it.\n recordingResult: result(recordingResult.value.outputPath!),\n };\n }\n case 'android': {\n const { outputPath } = await AndroidEmulatorUtils.stopScreenRecordingAsync({\n serialId: deviceIdentifier as AndroidDeviceSerialId,\n recordingSpawn: recordingResult.value.recordingSpawn,\n env,\n });\n return { fnResult, recordingResult: result(outputPath) };\n }\n }\n } catch (err) {\n logger.warn('Failed to stop screen recording.', err);\n\n return { fnResult, recordingResult: result(err as Error) };\n }\n}\n"]}
1
+ {"version":3,"file":"internalMaestroTest.js","sourceRoot":"","sources":["../../../src/steps/functions/internalMaestroTest.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { setTimeout } from 'node:timers/promises';\n\nimport {\n BuildFunction,\n BuildStepEnv,\n BuildStepInput,\n BuildStepInputValueTypeName,\n spawnAsync,\n} from '@expo/steps';\nimport { z } from 'zod';\nimport spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';\nimport { PipeMode, bunyan } from '@expo/logger';\nimport { Result, asyncResult, result } from '@expo/results';\nimport { GenericArtifactType } from '@expo/eas-build-job';\n\nimport { CustomBuildContext } from '../../customBuildContext';\nimport { IosSimulatorName, IosSimulatorUtils } from '../../utils/IosSimulatorUtils';\nimport {\n AndroidDeviceSerialId,\n AndroidEmulatorUtils,\n AndroidVirtualDeviceName,\n} from '../../utils/AndroidEmulatorUtils';\nimport { PlatformToProperNounMap } from '../../utils/strings';\nimport { findMaestroPathsFlowsToExecuteAsync } from '../../utils/findMaestroPathsFlowsToExecuteAsync';\n\nexport function createInternalEasMaestroTestFunction(ctx: CustomBuildContext): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: '__maestro_test',\n inputProviders: [\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'platform',\n required: true,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.JSON,\n id: 'flow_paths',\n required: true,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n id: 'retries',\n defaultValue: 1,\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'include_tags',\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'exclude_tags',\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n id: 'shards',\n defaultValue: 1,\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n id: 'output_format',\n required: false,\n }),\n BuildStepInput.createProvider({\n allowedValueTypeName: BuildStepInputValueTypeName.BOOLEAN,\n id: 'record_screen',\n defaultValue: false,\n required: false,\n }),\n ],\n fn: async (stepCtx, { inputs: _inputs, env }) => {\n // inputs come in form of { value: unknown }. Here we parse them into a typed and validated object.\n const {\n platform,\n flow_paths,\n retries,\n include_tags,\n exclude_tags,\n shards,\n output_format,\n record_screen,\n } = z\n .object({\n platform: z.enum(['ios', 'android']),\n flow_paths: z.array(z.string()),\n retries: z.number().default(1),\n include_tags: z.string().optional(),\n exclude_tags: z.string().optional(),\n shards: z.number().default(1),\n output_format: z.string().optional(),\n record_screen: z.boolean().default(false),\n })\n .parse(\n Object.fromEntries(Object.entries(_inputs).map(([key, value]) => [key, value.value]))\n );\n\n const flowPathsToExecute: string[] = [];\n for (const flowPath of flow_paths) {\n const flowPaths = await findMaestroPathsFlowsToExecuteAsync({\n workingDirectory: stepCtx.workingDirectory,\n flowPath,\n logger: stepCtx.logger,\n includeTags: include_tags ? include_tags.split(',') : undefined,\n excludeTags: exclude_tags ? exclude_tags.split(',') : undefined,\n });\n if (flowPaths.length === 0) {\n stepCtx.logger.warn(`No flows to execute found in \"${flowPath}\".`);\n continue;\n }\n stepCtx.logger.info(\n `Marking for execution:\\n- ${flowPaths.map((flowPath) => path.relative(stepCtx.workingDirectory, flowPath)).join('\\n- ')}`\n );\n stepCtx.logger.info('');\n flowPathsToExecute.push(...flowPaths);\n }\n\n // TODO: Add support for shards. (Shouldn't be too difficult.)\n if (shards > 1) {\n stepCtx.logger.warn(\n 'Sharding support has been temporarily disabled. Running tests on a single shard.'\n );\n }\n\n // eas/__maestro_test does not start devices, it expects a single device to be already running\n // and configured with the app. Here we find the booted device and stop it.\n\n let sourceDeviceIdentifier: IosSimulatorName | AndroidVirtualDeviceName;\n\n switch (platform) {\n case 'ios': {\n const bootedDevices = await IosSimulatorUtils.getAvailableDevicesAsync({\n env,\n filter: 'booted',\n });\n if (bootedDevices.length === 0) {\n throw new Error('No booted iOS Simulator found.');\n } else if (bootedDevices.length > 1) {\n throw new Error('Multiple booted iOS Simulators found.');\n }\n\n const device = bootedDevices[0];\n stepCtx.logger.info(`Running tests on iOS Simulator: ${device.name}.`);\n\n stepCtx.logger.info(`Preparing Simulator for tests...`);\n await spawnAsync('xcrun', ['simctl', 'shutdown', device.udid], {\n logger: stepCtx.logger,\n stdio: 'pipe',\n });\n\n sourceDeviceIdentifier = device.name;\n break;\n }\n case 'android': {\n const connectedDevices = await AndroidEmulatorUtils.getAttachedDevicesAsync({ env });\n if (connectedDevices.length === 0) {\n throw new Error('No booted Android Emulator found.');\n } else if (connectedDevices.length > 1) {\n throw new Error('Multiple booted Android Emulators found.');\n }\n\n const { serialId } = connectedDevices[0];\n const adbEmuAvdNameResult = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n mode: PipeMode.COMBINED,\n env,\n });\n const avdName = adbEmuAvdNameResult.stdout\n .replace(/\\r\\n/g, '\\n')\n .split('\\n')[0] as AndroidVirtualDeviceName;\n stepCtx.logger.info(`Running tests on Android Emulator: ${avdName}.`);\n\n stepCtx.logger.info(`Preparing Emulator for tests...`);\n await spawnAsync('adb', ['-s', serialId, 'emu', 'kill'], {\n stdio: 'pipe',\n });\n // Waiting for emulator to get killed, see ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL.\n await setTimeout(1000);\n\n sourceDeviceIdentifier = avdName;\n break;\n }\n }\n\n // During tests we generate reports and device logs. We store them in temporary directories\n // and upload them once all tests are done. When a test is retried, new reports overwrite\n // the old ones. The files are named \"flow-${index}\" for easier identification.\n const maestroReportsDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), 'maestro-reports-')\n );\n const deviceLogsDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'device-logs-'));\n\n const failedFlows: string[] = [];\n\n for (const [flowIndex, flowPath] of flowPathsToExecute.entries()) {\n stepCtx.logger.info('');\n\n // If output_format is empty or noop, we won't use this.\n const outputPath = path.join(\n maestroReportsDir,\n [\n `${output_format + '-' ?? ''}report-flow-${flowIndex + 1}`,\n MaestroOutputFormatToExtensionMap[output_format ?? 'noop'],\n ]\n .filter(Boolean)\n .join('.')\n );\n\n for (let attemptCount = 0; attemptCount < retries; attemptCount++) {\n const localDeviceName = `eas-simulator-${flowIndex}-${attemptCount}` as\n | IosSimulatorName\n | AndroidVirtualDeviceName;\n\n // If the test passes, but the recording fails, we don't want to make the test fail,\n // so we return two separate results.\n const {\n fnResult: { fnResult, recordingResult },\n logsResult,\n } = await withCleanDeviceAsync({\n platform,\n sourceDeviceIdentifier,\n localDeviceName,\n env,\n logger: stepCtx.logger,\n fn: async ({ deviceIdentifier }) => {\n return await maybeWithScreenRecordingAsync({\n shouldRecord: record_screen,\n platform,\n deviceIdentifier,\n env,\n logger: stepCtx.logger,\n fn: async () => {\n stepCtx.logger.info('');\n\n const [command, ...args] = getMaestroTestCommand({\n flow_path: flowPath,\n output_format,\n output_path: outputPath,\n });\n\n try {\n await spawnAsync(command, args, {\n logger: stepCtx.logger,\n cwd: stepCtx.workingDirectory,\n env,\n stdio: 'pipe',\n });\n } finally {\n stepCtx.logger.info('');\n }\n },\n });\n },\n });\n\n // Move device logs to the device logs directory.\n if (logsResult?.ok) {\n try {\n const extension = path.extname(logsResult.value.outputPath);\n const destinationPath = path.join(deviceLogsDir, `flow-${flowIndex}${extension}`);\n\n await fs.promises.rm(destinationPath, {\n force: true,\n recursive: true,\n });\n await fs.promises.rename(logsResult.value.outputPath, destinationPath);\n } catch (err) {\n stepCtx.logger.warn({ err }, 'Failed to prepare device logs for upload.');\n }\n } else if (logsResult?.reason) {\n stepCtx.logger.error({ err: logsResult.reason }, 'Failed to collect device logs.');\n }\n\n const isLastAttempt = fnResult.ok || attemptCount === retries - 1;\n if (isLastAttempt && recordingResult.value) {\n try {\n await ctx.runtimeApi.uploadArtifact({\n logger: stepCtx.logger,\n artifact: {\n // TODO(sjchmiela): Add metadata to artifacts so we don't need to encode flow path and attempt in the name.\n name: `Screen Recording (${flowIndex}-${path.basename(flowPath, path.extname(flowPath))})`,\n paths: [recordingResult.value],\n type: GenericArtifactType.OTHER,\n },\n });\n } catch (err) {\n stepCtx.logger.warn({ err }, 'Failed to upload screen recording.');\n }\n }\n\n if (fnResult.ok) {\n stepCtx.logger.info(`Test passed.`);\n // Break out of the retry loop.\n break;\n }\n\n if (attemptCount < retries - 1) {\n stepCtx.logger.info(`Retrying test...`);\n stepCtx.logger.info('');\n continue;\n }\n\n // fnResult.reason is not super interesting, but it does print out the full command so we can keep it for debugging purposes.\n stepCtx.logger.error({ err: fnResult.reason }, 'Test errored.');\n failedFlows.push(flowPath);\n }\n }\n\n stepCtx.logger.info('');\n\n // When all tests are done, we upload the reports and device logs.\n const generatedMaestroReports = await fs.promises.readdir(maestroReportsDir);\n if (generatedMaestroReports.length === 0) {\n stepCtx.logger.warn('No reports were generated.');\n } else {\n stepCtx.logger.info(`Uploading reports...`);\n try {\n await ctx.runtimeApi.uploadArtifact({\n logger: stepCtx.logger,\n artifact: {\n name: `${PlatformToProperNounMap[platform]} Maestro Test Reports (${output_format})`,\n paths: [maestroReportsDir],\n type: GenericArtifactType.OTHER,\n },\n });\n } catch (err) {\n stepCtx.logger.error({ err }, 'Failed to upload reports.');\n }\n }\n\n const generatedDeviceLogs = await fs.promises.readdir(deviceLogsDir);\n if (generatedDeviceLogs.length === 0) {\n stepCtx.logger.warn('No device logs were successfully collected.');\n } else {\n stepCtx.logger.info(`Uploading device logs...`);\n try {\n await ctx.runtimeApi.uploadArtifact({\n logger: stepCtx.logger,\n artifact: {\n name: `Maestro Test Device Logs`,\n paths: [deviceLogsDir],\n type: GenericArtifactType.OTHER,\n },\n });\n } catch (err) {\n stepCtx.logger.error({ err }, 'Failed to upload device logs.');\n }\n }\n\n stepCtx.logger.info('');\n\n // If any tests failed, we throw an error to mark the step as failed.\n if (failedFlows.length > 0) {\n throw new Error(\n `Some Maestro tests failed:\\n- ${failedFlows\n .map((flowPath) => path.relative(stepCtx.workingDirectory, flowPath))\n .join('\\n- ')}`\n );\n } else {\n stepCtx.logger.info('All Maestro tests passed.');\n }\n },\n });\n}\n\nexport function getMaestroTestCommand(params: {\n flow_path: string;\n output_format: string | undefined;\n /** Unused if `output_format` is undefined */\n output_path: string;\n}): [command: string, ...args: string[]] {\n let outputFormatFlags: string[] = [];\n if (params.output_format) {\n outputFormatFlags = [`--format`, params.output_format, `--output`, params.output_path];\n }\n\n return ['maestro', 'test', ...outputFormatFlags, params.flow_path] as [\n command: string,\n ...args: string[],\n ];\n}\n\nconst MaestroOutputFormatToExtensionMap: Record<string, string | undefined> = {\n junit: 'xml',\n html: 'html',\n};\n\nasync function withCleanDeviceAsync<TResult>({\n platform,\n sourceDeviceIdentifier,\n localDeviceName,\n env,\n logger,\n fn,\n}: {\n env: BuildStepEnv;\n logger: bunyan;\n platform: 'ios' | 'android';\n sourceDeviceIdentifier: IosSimulatorName | AndroidVirtualDeviceName;\n localDeviceName: IosSimulatorName | AndroidVirtualDeviceName;\n fn: ({\n deviceIdentifier,\n }: {\n deviceIdentifier: IosSimulatorName | AndroidDeviceSerialId;\n }) => Promise<TResult>;\n}): Promise<{ fnResult: TResult; logsResult: Result<{ outputPath: string }> | null }> {\n // Clone and start the device\n\n let localDeviceIdentifier: IosSimulatorName | AndroidDeviceSerialId;\n\n switch (platform) {\n case 'ios': {\n logger.info(`Cloning iOS Simulator ${sourceDeviceIdentifier} to ${localDeviceName}...`);\n await IosSimulatorUtils.cloneAsync({\n sourceDeviceIdentifier: sourceDeviceIdentifier as IosSimulatorName,\n destinationDeviceName: localDeviceName as IosSimulatorName,\n env,\n });\n logger.info(`Starting iOS Simulator ${localDeviceName}...`);\n const { udid } = await IosSimulatorUtils.startAsync({\n deviceIdentifier: localDeviceName as IosSimulatorName,\n env,\n });\n logger.info(`Waiting for iOS Simulator ${localDeviceName} to be ready...`);\n await IosSimulatorUtils.waitForReadyAsync({\n udid,\n env,\n });\n localDeviceIdentifier = localDeviceName as IosSimulatorName;\n break;\n }\n case 'android': {\n logger.info(`Cloning Android Emulator ${sourceDeviceIdentifier} to ${localDeviceName}...`);\n await AndroidEmulatorUtils.cloneAsync({\n sourceDeviceName: sourceDeviceIdentifier as AndroidVirtualDeviceName,\n destinationDeviceName: localDeviceName as AndroidVirtualDeviceName,\n env,\n logger,\n });\n logger.info(`Starting Android Emulator ${localDeviceName}...`);\n const { serialId } = await AndroidEmulatorUtils.startAsync({\n deviceName: localDeviceName as AndroidVirtualDeviceName,\n env,\n });\n logger.info(`Waiting for Android Emulator ${localDeviceName} to be ready...`);\n await AndroidEmulatorUtils.waitForReadyAsync({\n serialId,\n env,\n });\n localDeviceIdentifier = serialId;\n break;\n }\n }\n\n // Run the function\n\n const fnResult = await asyncResult(fn({ deviceIdentifier: localDeviceIdentifier }));\n\n // Stop the device\n\n let logsResult: Result<{ outputPath: string }> | null = null;\n\n try {\n switch (platform) {\n case 'ios': {\n logger.info(`Collecting logs from ${localDeviceName}...`);\n logsResult = await asyncResult(\n IosSimulatorUtils.collectLogsAsync({\n deviceIdentifier: localDeviceIdentifier as IosSimulatorName,\n env,\n })\n );\n\n logger.info(`Cleaning up ${localDeviceName}...`);\n await IosSimulatorUtils.deleteAsync({\n deviceIdentifier: localDeviceIdentifier as IosSimulatorName,\n env,\n });\n break;\n }\n case 'android': {\n logger.info(`Collecting logs from ${localDeviceName}...`);\n logsResult = await asyncResult(\n AndroidEmulatorUtils.collectLogsAsync({\n serialId: localDeviceIdentifier as AndroidDeviceSerialId,\n env,\n })\n );\n\n logger.info(`Cleaning up ${localDeviceName}...`);\n await AndroidEmulatorUtils.deleteAsync({\n serialId: localDeviceIdentifier as AndroidDeviceSerialId,\n env,\n });\n break;\n }\n }\n } catch (err) {\n logger.error(`Error cleaning up device: ${err}`);\n }\n\n return { fnResult: fnResult.enforceValue(), logsResult };\n}\n\n/** Runs provided `fn` function, optionally wrapping it with starting and stopping screen recording. */\nasync function maybeWithScreenRecordingAsync<TResult>({\n shouldRecord,\n platform,\n deviceIdentifier,\n env,\n logger,\n fn,\n}: {\n // As weird as it is, it's more convenient to have this function like `maybeWith...`\n // than \"withScreenRecordingAsync\" and `withScreenRecordingAsync(fn)` vs `fn` in the caller.\n shouldRecord: boolean;\n platform: 'ios' | 'android';\n deviceIdentifier: IosSimulatorName | AndroidDeviceSerialId;\n env: BuildStepEnv;\n logger: bunyan;\n fn: () => Promise<TResult>;\n}): Promise<{ fnResult: Result<TResult>; recordingResult: Result<string | null> }> {\n if (!shouldRecord) {\n return { fnResult: await asyncResult(fn()), recordingResult: result(null) };\n }\n\n let recordingResult: Result<{\n recordingSpawn: SpawnPromise<SpawnResult>;\n outputPath?: string;\n }>;\n\n // Start screen recording\n\n logger.info(`Starting screen recording on ${deviceIdentifier}...`);\n\n switch (platform) {\n case 'ios': {\n recordingResult = await asyncResult(\n IosSimulatorUtils.startScreenRecordingAsync({\n deviceIdentifier: deviceIdentifier as IosSimulatorName,\n env,\n })\n );\n break;\n }\n case 'android': {\n recordingResult = await asyncResult(\n AndroidEmulatorUtils.startScreenRecordingAsync({\n serialId: deviceIdentifier as AndroidDeviceSerialId,\n env,\n })\n );\n break;\n }\n }\n\n if (!recordingResult.ok) {\n logger.warn('Failed to start screen recording.', recordingResult.reason);\n }\n\n // Run the function\n\n const fnResult = await asyncResult(fn());\n\n // If recording failed there's nothing to stop, so we return the results\n\n if (!recordingResult.ok) {\n return { fnResult, recordingResult: result(recordingResult.reason) };\n }\n\n // If recording started, finish it\n\n try {\n logger.info(`Stopping screen recording on ${deviceIdentifier}...`);\n\n switch (platform) {\n case 'ios': {\n await IosSimulatorUtils.stopScreenRecordingAsync({\n recordingSpawn: recordingResult.value.recordingSpawn,\n });\n return {\n fnResult,\n // We know outputPath is defined, because startIosScreenRecording() should have filled it.\n recordingResult: result(recordingResult.value.outputPath!),\n };\n }\n case 'android': {\n const { outputPath } = await AndroidEmulatorUtils.stopScreenRecordingAsync({\n serialId: deviceIdentifier as AndroidDeviceSerialId,\n recordingSpawn: recordingResult.value.recordingSpawn,\n env,\n });\n return { fnResult, recordingResult: result(outputPath) };\n }\n }\n } catch (err) {\n logger.warn('Failed to stop screen recording.', err);\n\n return { fnResult, recordingResult: result(err as Error) };\n }\n}\n"]}
@@ -87,16 +87,25 @@ var AndroidEmulatorUtils;
87
87
  AndroidEmulatorUtils.createAsync = createAsync;
88
88
  async function cloneAsync({ sourceDeviceName, destinationDeviceName, env, logger, }) {
89
89
  const cloneIniFile = `${env.HOME}/.android/avd/${destinationDeviceName}.ini`;
90
+ // Clean destination device files
90
91
  await node_fs_1.default.promises.rm(`${env.HOME}/.android/avd/${destinationDeviceName}.avd`, {
91
92
  recursive: true,
92
93
  force: true,
93
94
  });
94
95
  await node_fs_1.default.promises.rm(cloneIniFile, { force: true });
96
+ // Remove lockfiles from source device
97
+ const sourceLockfiles = await (0, fast_glob_1.default)('./**/*.lock', {
98
+ cwd: `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,
99
+ absolute: true,
100
+ });
101
+ await Promise.all(sourceLockfiles.map((lockfile) => node_fs_1.default.promises.rm(lockfile, { force: true })));
102
+ // Copy source to destination
95
103
  await node_fs_1.default.promises.cp(`${env.HOME}/.android/avd/${sourceDeviceName}.avd`, `${env.HOME}/.android/avd/${destinationDeviceName}.avd`, { recursive: true, verbatimSymlinks: true, force: true });
96
104
  await node_fs_1.default.promises.cp(`${env.HOME}/.android/avd/${sourceDeviceName}.ini`, cloneIniFile, {
97
105
  verbatimSymlinks: true,
98
106
  force: true,
99
107
  });
108
+ // Remove lockfiles from destination device
100
109
  const lockfiles = await (0, fast_glob_1.default)('./**/*.lock', {
101
110
  cwd: `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,
102
111
  absolute: true,
@@ -1 +1 @@
1
- {"version":3,"file":"AndroidEmulatorUtils.js","sourceRoot":"","sources":["../../src/utils/AndroidEmulatorUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport { setTimeout } from 'node:timers/promises';\nimport path from 'node:path';\n\nimport { bunyan } from '@expo/logger';\nimport spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';\nimport FastGlob from 'fast-glob';\nimport { z } from 'zod';\n\nimport { retryAsync } from './retry';\n\n/** Android Virtual Device is the device we run. */\nexport type AndroidVirtualDeviceName = string & z.BRAND<'AndroidVirtualDeviceName'>;\n/** Android device is configuration for the AVD -- screen size, etc. */\nexport type AndroidDeviceName = string & z.BRAND<'AndroidDeviceName'>;\nexport type AndroidDeviceSerialId = string & z.BRAND<'AndroidDeviceSerialId'>;\n\nexport namespace AndroidEmulatorUtils {\n export const defaultSystemImagePackage = `system-images;android-30;default;${\n process.arch === 'arm64' ? 'arm64-v8a' : 'x86_64'\n }`;\n\n export async function getAvailableDevicesAsync({\n env,\n }: {\n env: NodeJS.ProcessEnv;\n }): Promise<AndroidDeviceName[]> {\n const result = await spawn('avdmanager', ['list', 'device', '--compact', '--null'], { env });\n return result.stdout.split('\\0').filter((line) => line !== '') as AndroidDeviceName[];\n }\n\n export async function getAttachedDevicesAsync({\n env,\n }: {\n env: NodeJS.ProcessEnv;\n }): Promise<{ serialId: AndroidDeviceSerialId; state: 'offline' | 'device' }[]> {\n const result = await spawn('adb', ['devices', '-l'], {\n env,\n });\n return result.stdout\n .replace(/\\r\\n/g, '\\n')\n .split('\\n')\n .filter((line) => line.startsWith('emulator'))\n .map((line) => {\n const [serialId, state] = line.split(/\\s+/) as [\n AndroidDeviceSerialId,\n 'offline' | 'device',\n ];\n return {\n serialId,\n state,\n };\n });\n }\n\n export async function getSerialIdAsync({\n deviceName,\n env,\n }: {\n deviceName: AndroidVirtualDeviceName;\n env: NodeJS.ProcessEnv;\n }): Promise<AndroidDeviceSerialId | null> {\n const adbDevices = await spawn('adb', ['devices'], { env });\n for (const adbDeviceLine of adbDevices.stdout.split('\\n')) {\n if (!adbDeviceLine.startsWith('emulator')) {\n continue;\n }\n\n const matches = adbDeviceLine.match(/^(\\S+)/);\n if (!matches) {\n continue;\n }\n\n const [, serialId] = matches;\n // Previously we were using `qemu.uuid` to identify the emulator,\n // but this does not work for newer emulators, because there is\n // a limit on properties and custom properties get ignored.\n // See https://stackoverflow.com/questions/2214377/how-to-get-serial-number-or-id-of-android-emulator-after-it-runs#comment98259121_42038655\n const adbEmuAvdName = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n env,\n });\n if (adbEmuAvdName.stdout.replace(/\\r\\n/g, '\\n').split('\\n')[0] === deviceName) {\n return serialId as AndroidDeviceSerialId;\n }\n }\n\n return null;\n }\n\n export async function createAsync({\n deviceName,\n systemImagePackage,\n deviceIdentifier,\n env,\n }: {\n deviceName: AndroidVirtualDeviceName;\n systemImagePackage: string;\n deviceIdentifier: AndroidDeviceName | null;\n env: NodeJS.ProcessEnv;\n }): Promise<void> {\n const avdManager = spawn(\n 'avdmanager',\n [\n 'create',\n 'avd',\n '--name',\n deviceName,\n '--package',\n systemImagePackage,\n '--force',\n ...(deviceIdentifier ? ['--device', deviceIdentifier] : []),\n ],\n {\n env,\n stdio: 'pipe',\n }\n );\n // `avdmanager create` always asks about creating a custom hardware profile.\n // > Do you wish to create a custom hardware profile? [no]\n // We answer \"no\".\n avdManager.child.stdin?.write('no');\n avdManager.child.stdin?.end();\n await avdManager;\n }\n\n export async function cloneAsync({\n sourceDeviceName,\n destinationDeviceName,\n env,\n logger,\n }: {\n sourceDeviceName: AndroidVirtualDeviceName;\n destinationDeviceName: AndroidVirtualDeviceName;\n env: NodeJS.ProcessEnv;\n logger: bunyan;\n }): Promise<void> {\n const cloneIniFile = `${env.HOME}/.android/avd/${destinationDeviceName}.ini`;\n\n await fs.promises.rm(`${env.HOME}/.android/avd/${destinationDeviceName}.avd`, {\n recursive: true,\n force: true,\n });\n await fs.promises.rm(cloneIniFile, { force: true });\n\n await fs.promises.cp(\n `${env.HOME}/.android/avd/${sourceDeviceName}.avd`,\n `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,\n { recursive: true, verbatimSymlinks: true, force: true }\n );\n\n await fs.promises.cp(`${env.HOME}/.android/avd/${sourceDeviceName}.ini`, cloneIniFile, {\n verbatimSymlinks: true,\n force: true,\n });\n\n const lockfiles = await FastGlob('./**/*.lock', {\n cwd: `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,\n absolute: true,\n });\n\n await Promise.all(lockfiles.map((lockfile) => fs.promises.rm(lockfile, { force: true })));\n\n const filesToReplaceDeviceNameIn = // TODO: Test whether we need to use `spawnAsync` here.\n (\n await spawn('grep', [\n '--binary-files=without-match',\n '--recursive',\n '--files-with-matches',\n `${sourceDeviceName}`,\n `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,\n ])\n ).stdout\n .split('\\n')\n .filter((file) => file !== '');\n\n for (const file of [...filesToReplaceDeviceNameIn, cloneIniFile]) {\n try {\n const txtFile = await fs.promises.readFile(file, 'utf-8');\n const replaceRegex = new RegExp(`${sourceDeviceName}`, 'g');\n const updatedTxtFile = txtFile.replace(replaceRegex, destinationDeviceName);\n await fs.promises.writeFile(file, updatedTxtFile);\n } catch (err) {\n logger.warn({ err }, `Failed to replace device name in ${file}.`);\n }\n }\n }\n\n export async function startAsync({\n deviceName,\n env,\n }: {\n deviceName: AndroidVirtualDeviceName;\n env: NodeJS.ProcessEnv;\n }): Promise<{ emulatorPromise: SpawnPromise<SpawnResult>; serialId: AndroidDeviceSerialId }> {\n const emulatorPromise = spawn(\n `${process.env.ANDROID_HOME}/emulator/emulator`,\n [\n '-no-window',\n '-no-boot-anim',\n '-writable-system',\n '-noaudio',\n '-memory',\n '8192',\n '-no-snapshot-save',\n '-avd',\n deviceName,\n ],\n {\n detached: true,\n stdio: 'inherit',\n env: {\n ...env,\n // We don't need to wait for emulator to exit gracefully.\n ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL: '1',\n },\n }\n );\n // If emulator fails to start, throw its error.\n if (!emulatorPromise.child.pid) {\n await emulatorPromise;\n }\n emulatorPromise.child.unref();\n\n const serialId = await retryAsync(\n async () => {\n const serialId = await getSerialIdAsync({ deviceName, env });\n assert(\n serialId,\n `Failed to configure emulator (${serialId}): emulator with required ID not found.`\n );\n return serialId;\n },\n {\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n // We don't want to await the SpawnPromise here.\n // eslint-disable-next-line @typescript-eslint/return-await\n return { emulatorPromise, serialId };\n }\n\n export async function waitForReadyAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<void> {\n await retryAsync(\n async () => {\n const { stdout } = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'getprop', 'sys.boot_completed'],\n { env }\n );\n\n if (!stdout.startsWith('1')) {\n throw new Error(`Emulator (${serialId}) boot has not completed.`);\n }\n },\n {\n // Retry every second for 3 minutes.\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n }\n\n export async function collectLogsAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<{ outputPath: string }> {\n const outputDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'android-emulator-logs-'));\n const outputPath = path.join(outputDir, `${serialId}.log`);\n\n // Pipe adb logcat output directly to the file to avoid loading it all into memory\n await new Promise<void>((resolve, reject) => {\n const { child } = spawn('adb', ['-s', serialId, 'logcat', '-d'], {\n env,\n stdio: ['ignore', 'pipe', 'inherit'],\n });\n\n if (!child.stdout) {\n reject(new Error('\"adb logcat\" did not start correctly.'));\n return;\n }\n\n const writeStream = fs.createWriteStream(outputPath);\n child.stdout.pipe(writeStream);\n child.stdout.on('error', reject);\n\n child.on('error', reject);\n writeStream.on('error', reject);\n\n child.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`\"adb logcat\" exited with code ${code}`));\n }\n });\n });\n\n return { outputPath };\n }\n\n export async function deleteAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<void> {\n const adbEmuAvdName = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n env,\n });\n const deviceName = adbEmuAvdName.stdout.replace(/\\r\\n/g, '\\n').split('\\n')[0];\n\n await spawn('adb', ['-s', serialId, 'emu', 'kill'], { env });\n\n await retryAsync(\n async () => {\n const devices = await getAttachedDevicesAsync({ env });\n if (devices.some((device) => device.serialId === serialId)) {\n throw new Error(`Emulator (${serialId}) is still attached.`);\n }\n },\n {\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n await spawn('avdmanager', ['delete', 'avd', '-n', deviceName], { env });\n }\n\n export async function startScreenRecordingAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<{\n recordingSpawn: SpawnPromise<SpawnResult>;\n }> {\n let isReady = false;\n\n // Ensure /sdcard/ is ready to write to. (If the emulator was just booted, it might not be ready yet.)\n for (let i = 0; i < 30; i++) {\n try {\n await spawn('adb', ['-s', serialId, 'shell', 'touch', '/sdcard/.expo-recording-ready'], {\n env,\n });\n isReady = true;\n break;\n } catch {\n await setTimeout(1000);\n }\n }\n\n if (!isReady) {\n throw new Error(`Emulator (${serialId}) filesystem was not ready in time.`);\n }\n\n const screenrecordArgs = [\n '-s',\n serialId,\n 'shell',\n 'screenrecord',\n '--verbose',\n '/sdcard/expo-recording.mp4',\n ];\n\n const screenrecordHelp = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'screenrecord', '--help'],\n {\n env,\n }\n );\n\n if (screenrecordHelp.stdout.includes('remove the time limit')) {\n screenrecordArgs.push('--time-limit', '0');\n }\n\n const recordingSpawn = spawn('adb', screenrecordArgs, {\n env,\n stdio: 'pipe',\n });\n recordingSpawn.child.unref();\n\n // We are returning the SpawnPromise here, so we don't await it.\n // eslint-disable-next-line @typescript-eslint/return-await\n return {\n recordingSpawn,\n };\n }\n\n export async function stopScreenRecordingAsync({\n serialId,\n recordingSpawn,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n recordingSpawn: SpawnPromise<SpawnResult>;\n env: NodeJS.ProcessEnv;\n }): Promise<{ outputPath: string }> {\n recordingSpawn.child.kill(1);\n\n try {\n await recordingSpawn;\n } catch {\n // do nothing\n }\n\n let isRecordingBusy = true;\n for (let i = 0; i < 30; i++) {\n const lsof = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'lsof -t /sdcard/expo-recording.mp4'],\n { env }\n );\n if (lsof.stdout.trim() === '') {\n isRecordingBusy = false;\n break;\n }\n await setTimeout(1000);\n }\n\n if (isRecordingBusy) {\n throw new Error(`Recording file is busy.`);\n }\n\n const outputDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), 'android-screen-recording-')\n );\n const outputPath = path.join(outputDir, `${serialId}.mp4`);\n\n await spawn('adb', ['-s', serialId, 'pull', '/sdcard/expo-recording.mp4', outputPath], { env });\n\n return { outputPath };\n }\n}\n"]}
1
+ {"version":3,"file":"AndroidEmulatorUtils.js","sourceRoot":"","sources":["../../src/utils/AndroidEmulatorUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport { setTimeout } from 'node:timers/promises';\nimport path from 'node:path';\n\nimport { bunyan } from '@expo/logger';\nimport spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';\nimport FastGlob from 'fast-glob';\nimport { z } from 'zod';\n\nimport { retryAsync } from './retry';\n\n/** Android Virtual Device is the device we run. */\nexport type AndroidVirtualDeviceName = string & z.BRAND<'AndroidVirtualDeviceName'>;\n/** Android device is configuration for the AVD -- screen size, etc. */\nexport type AndroidDeviceName = string & z.BRAND<'AndroidDeviceName'>;\nexport type AndroidDeviceSerialId = string & z.BRAND<'AndroidDeviceSerialId'>;\n\nexport namespace AndroidEmulatorUtils {\n export const defaultSystemImagePackage = `system-images;android-30;default;${\n process.arch === 'arm64' ? 'arm64-v8a' : 'x86_64'\n }`;\n\n export async function getAvailableDevicesAsync({\n env,\n }: {\n env: NodeJS.ProcessEnv;\n }): Promise<AndroidDeviceName[]> {\n const result = await spawn('avdmanager', ['list', 'device', '--compact', '--null'], { env });\n return result.stdout.split('\\0').filter((line) => line !== '') as AndroidDeviceName[];\n }\n\n export async function getAttachedDevicesAsync({\n env,\n }: {\n env: NodeJS.ProcessEnv;\n }): Promise<{ serialId: AndroidDeviceSerialId; state: 'offline' | 'device' }[]> {\n const result = await spawn('adb', ['devices', '-l'], {\n env,\n });\n return result.stdout\n .replace(/\\r\\n/g, '\\n')\n .split('\\n')\n .filter((line) => line.startsWith('emulator'))\n .map((line) => {\n const [serialId, state] = line.split(/\\s+/) as [\n AndroidDeviceSerialId,\n 'offline' | 'device',\n ];\n return {\n serialId,\n state,\n };\n });\n }\n\n export async function getSerialIdAsync({\n deviceName,\n env,\n }: {\n deviceName: AndroidVirtualDeviceName;\n env: NodeJS.ProcessEnv;\n }): Promise<AndroidDeviceSerialId | null> {\n const adbDevices = await spawn('adb', ['devices'], { env });\n for (const adbDeviceLine of adbDevices.stdout.split('\\n')) {\n if (!adbDeviceLine.startsWith('emulator')) {\n continue;\n }\n\n const matches = adbDeviceLine.match(/^(\\S+)/);\n if (!matches) {\n continue;\n }\n\n const [, serialId] = matches;\n // Previously we were using `qemu.uuid` to identify the emulator,\n // but this does not work for newer emulators, because there is\n // a limit on properties and custom properties get ignored.\n // See https://stackoverflow.com/questions/2214377/how-to-get-serial-number-or-id-of-android-emulator-after-it-runs#comment98259121_42038655\n const adbEmuAvdName = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n env,\n });\n if (adbEmuAvdName.stdout.replace(/\\r\\n/g, '\\n').split('\\n')[0] === deviceName) {\n return serialId as AndroidDeviceSerialId;\n }\n }\n\n return null;\n }\n\n export async function createAsync({\n deviceName,\n systemImagePackage,\n deviceIdentifier,\n env,\n }: {\n deviceName: AndroidVirtualDeviceName;\n systemImagePackage: string;\n deviceIdentifier: AndroidDeviceName | null;\n env: NodeJS.ProcessEnv;\n }): Promise<void> {\n const avdManager = spawn(\n 'avdmanager',\n [\n 'create',\n 'avd',\n '--name',\n deviceName,\n '--package',\n systemImagePackage,\n '--force',\n ...(deviceIdentifier ? ['--device', deviceIdentifier] : []),\n ],\n {\n env,\n stdio: 'pipe',\n }\n );\n // `avdmanager create` always asks about creating a custom hardware profile.\n // > Do you wish to create a custom hardware profile? [no]\n // We answer \"no\".\n avdManager.child.stdin?.write('no');\n avdManager.child.stdin?.end();\n await avdManager;\n }\n\n export async function cloneAsync({\n sourceDeviceName,\n destinationDeviceName,\n env,\n logger,\n }: {\n sourceDeviceName: AndroidVirtualDeviceName;\n destinationDeviceName: AndroidVirtualDeviceName;\n env: NodeJS.ProcessEnv;\n logger: bunyan;\n }): Promise<void> {\n const cloneIniFile = `${env.HOME}/.android/avd/${destinationDeviceName}.ini`;\n\n // Clean destination device files\n await fs.promises.rm(`${env.HOME}/.android/avd/${destinationDeviceName}.avd`, {\n recursive: true,\n force: true,\n });\n await fs.promises.rm(cloneIniFile, { force: true });\n\n // Remove lockfiles from source device\n const sourceLockfiles = await FastGlob('./**/*.lock', {\n cwd: `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,\n absolute: true,\n });\n await Promise.all(sourceLockfiles.map((lockfile) => fs.promises.rm(lockfile, { force: true })));\n\n // Copy source to destination\n await fs.promises.cp(\n `${env.HOME}/.android/avd/${sourceDeviceName}.avd`,\n `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,\n { recursive: true, verbatimSymlinks: true, force: true }\n );\n\n await fs.promises.cp(`${env.HOME}/.android/avd/${sourceDeviceName}.ini`, cloneIniFile, {\n verbatimSymlinks: true,\n force: true,\n });\n\n // Remove lockfiles from destination device\n const lockfiles = await FastGlob('./**/*.lock', {\n cwd: `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,\n absolute: true,\n });\n\n await Promise.all(lockfiles.map((lockfile) => fs.promises.rm(lockfile, { force: true })));\n\n const filesToReplaceDeviceNameIn = // TODO: Test whether we need to use `spawnAsync` here.\n (\n await spawn('grep', [\n '--binary-files=without-match',\n '--recursive',\n '--files-with-matches',\n `${sourceDeviceName}`,\n `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,\n ])\n ).stdout\n .split('\\n')\n .filter((file) => file !== '');\n\n for (const file of [...filesToReplaceDeviceNameIn, cloneIniFile]) {\n try {\n const txtFile = await fs.promises.readFile(file, 'utf-8');\n const replaceRegex = new RegExp(`${sourceDeviceName}`, 'g');\n const updatedTxtFile = txtFile.replace(replaceRegex, destinationDeviceName);\n await fs.promises.writeFile(file, updatedTxtFile);\n } catch (err) {\n logger.warn({ err }, `Failed to replace device name in ${file}.`);\n }\n }\n }\n\n export async function startAsync({\n deviceName,\n env,\n }: {\n deviceName: AndroidVirtualDeviceName;\n env: NodeJS.ProcessEnv;\n }): Promise<{ emulatorPromise: SpawnPromise<SpawnResult>; serialId: AndroidDeviceSerialId }> {\n const emulatorPromise = spawn(\n `${process.env.ANDROID_HOME}/emulator/emulator`,\n [\n '-no-window',\n '-no-boot-anim',\n '-writable-system',\n '-noaudio',\n '-memory',\n '8192',\n '-no-snapshot-save',\n '-avd',\n deviceName,\n ],\n {\n detached: true,\n stdio: 'inherit',\n env: {\n ...env,\n // We don't need to wait for emulator to exit gracefully.\n ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL: '1',\n },\n }\n );\n // If emulator fails to start, throw its error.\n if (!emulatorPromise.child.pid) {\n await emulatorPromise;\n }\n emulatorPromise.child.unref();\n\n const serialId = await retryAsync(\n async () => {\n const serialId = await getSerialIdAsync({ deviceName, env });\n assert(\n serialId,\n `Failed to configure emulator (${serialId}): emulator with required ID not found.`\n );\n return serialId;\n },\n {\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n // We don't want to await the SpawnPromise here.\n // eslint-disable-next-line @typescript-eslint/return-await\n return { emulatorPromise, serialId };\n }\n\n export async function waitForReadyAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<void> {\n await retryAsync(\n async () => {\n const { stdout } = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'getprop', 'sys.boot_completed'],\n { env }\n );\n\n if (!stdout.startsWith('1')) {\n throw new Error(`Emulator (${serialId}) boot has not completed.`);\n }\n },\n {\n // Retry every second for 3 minutes.\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n }\n\n export async function collectLogsAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<{ outputPath: string }> {\n const outputDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'android-emulator-logs-'));\n const outputPath = path.join(outputDir, `${serialId}.log`);\n\n // Pipe adb logcat output directly to the file to avoid loading it all into memory\n await new Promise<void>((resolve, reject) => {\n const { child } = spawn('adb', ['-s', serialId, 'logcat', '-d'], {\n env,\n stdio: ['ignore', 'pipe', 'inherit'],\n });\n\n if (!child.stdout) {\n reject(new Error('\"adb logcat\" did not start correctly.'));\n return;\n }\n\n const writeStream = fs.createWriteStream(outputPath);\n child.stdout.pipe(writeStream);\n child.stdout.on('error', reject);\n\n child.on('error', reject);\n writeStream.on('error', reject);\n\n child.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`\"adb logcat\" exited with code ${code}`));\n }\n });\n });\n\n return { outputPath };\n }\n\n export async function deleteAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<void> {\n const adbEmuAvdName = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n env,\n });\n const deviceName = adbEmuAvdName.stdout.replace(/\\r\\n/g, '\\n').split('\\n')[0];\n\n await spawn('adb', ['-s', serialId, 'emu', 'kill'], { env });\n\n await retryAsync(\n async () => {\n const devices = await getAttachedDevicesAsync({ env });\n if (devices.some((device) => device.serialId === serialId)) {\n throw new Error(`Emulator (${serialId}) is still attached.`);\n }\n },\n {\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n await spawn('avdmanager', ['delete', 'avd', '-n', deviceName], { env });\n }\n\n export async function startScreenRecordingAsync({\n serialId,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n env: NodeJS.ProcessEnv;\n }): Promise<{\n recordingSpawn: SpawnPromise<SpawnResult>;\n }> {\n let isReady = false;\n\n // Ensure /sdcard/ is ready to write to. (If the emulator was just booted, it might not be ready yet.)\n for (let i = 0; i < 30; i++) {\n try {\n await spawn('adb', ['-s', serialId, 'shell', 'touch', '/sdcard/.expo-recording-ready'], {\n env,\n });\n isReady = true;\n break;\n } catch {\n await setTimeout(1000);\n }\n }\n\n if (!isReady) {\n throw new Error(`Emulator (${serialId}) filesystem was not ready in time.`);\n }\n\n const screenrecordArgs = [\n '-s',\n serialId,\n 'shell',\n 'screenrecord',\n '--verbose',\n '/sdcard/expo-recording.mp4',\n ];\n\n const screenrecordHelp = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'screenrecord', '--help'],\n {\n env,\n }\n );\n\n if (screenrecordHelp.stdout.includes('remove the time limit')) {\n screenrecordArgs.push('--time-limit', '0');\n }\n\n const recordingSpawn = spawn('adb', screenrecordArgs, {\n env,\n stdio: 'pipe',\n });\n recordingSpawn.child.unref();\n\n // We are returning the SpawnPromise here, so we don't await it.\n // eslint-disable-next-line @typescript-eslint/return-await\n return {\n recordingSpawn,\n };\n }\n\n export async function stopScreenRecordingAsync({\n serialId,\n recordingSpawn,\n env,\n }: {\n serialId: AndroidDeviceSerialId;\n recordingSpawn: SpawnPromise<SpawnResult>;\n env: NodeJS.ProcessEnv;\n }): Promise<{ outputPath: string }> {\n recordingSpawn.child.kill(1);\n\n try {\n await recordingSpawn;\n } catch {\n // do nothing\n }\n\n let isRecordingBusy = true;\n for (let i = 0; i < 30; i++) {\n const lsof = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'lsof -t /sdcard/expo-recording.mp4'],\n { env }\n );\n if (lsof.stdout.trim() === '') {\n isRecordingBusy = false;\n break;\n }\n await setTimeout(1000);\n }\n\n if (isRecordingBusy) {\n throw new Error(`Recording file is busy.`);\n }\n\n const outputDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), 'android-screen-recording-')\n );\n const outputPath = path.join(outputDir, `${serialId}.mp4`);\n\n await spawn('adb', ['-s', serialId, 'pull', '/sdcard/expo-recording.mp4', outputPath], { env });\n\n return { outputPath };\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "1.0.202",
3
+ "version": "1.0.204",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -27,13 +27,13 @@
27
27
  "@expo/config": "10.0.6",
28
28
  "@expo/config-plugins": "9.0.12",
29
29
  "@expo/downloader": "1.0.118",
30
- "@expo/eas-build-job": "1.0.201",
30
+ "@expo/eas-build-job": "1.0.204",
31
31
  "@expo/env": "^0.4.0",
32
32
  "@expo/logger": "1.0.117",
33
33
  "@expo/package-manager": "1.7.0",
34
34
  "@expo/plist": "^0.2.0",
35
35
  "@expo/results": "^1.0.0",
36
- "@expo/steps": "1.0.201",
36
+ "@expo/steps": "1.0.204",
37
37
  "@expo/template-file": "1.0.117",
38
38
  "@expo/turtle-spawn": "1.0.117",
39
39
  "@expo/xcpretty": "^4.3.1",
@@ -79,5 +79,5 @@
79
79
  "node": "20.14.0",
80
80
  "yarn": "1.22.21"
81
81
  },
82
- "gitHead": "ea91454ff19be7fbf7ee7f7b5e1428be04475341"
82
+ "gitHead": "a058b16a0e415607dd21180e81e2d8299a688af0"
83
83
  }