@expo/build-tools 1.0.201 → 1.0.203

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
  },
@@ -354,6 +357,7 @@ async function withCleanDeviceAsync({ platform, sourceDeviceIdentifier, localDev
354
357
  sourceDeviceName: sourceDeviceIdentifier,
355
358
  destinationDeviceName: localDeviceName,
356
359
  env,
360
+ logger,
357
361
  });
358
362
  logger.info(`Starting Android Emulator ${localDeviceName}...`);
359
363
  const { serialId } = await AndroidEmulatorUtils_1.AndroidEmulatorUtils.startAsync({
@@ -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 });\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"]}
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createStartAndroidEmulatorBuildFunction = void 0;
7
7
  const steps_1 = require("@expo/steps");
8
8
  const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
9
+ const results_1 = require("@expo/results");
9
10
  const retry_1 = require("../../utils/retry");
10
11
  const AndroidEmulatorUtils_1 = require("../../utils/AndroidEmulatorUtils");
11
12
  function createStartAndroidEmulatorBuildFunction() {
@@ -92,7 +93,8 @@ function createStartAndroidEmulatorBuildFunction() {
92
93
  env,
93
94
  });
94
95
  // Waiting for source emulator to shutdown.
95
- await emulatorPromise;
96
+ // We don't care about resolved/rejected.
97
+ await (0, results_1.asyncResult)(emulatorPromise);
96
98
  for (let i = 0; i < count; i++) {
97
99
  const cloneIdentifier = `eas-simulator-${i + 1}`;
98
100
  logger.info(`Cloning ${deviceName} to ${cloneIdentifier}...`);
@@ -100,6 +102,7 @@ function createStartAndroidEmulatorBuildFunction() {
100
102
  sourceDeviceName: deviceName,
101
103
  destinationDeviceName: cloneIdentifier,
102
104
  env,
105
+ logger,
103
106
  });
104
107
  logger.info('Starting emulator device');
105
108
  const { serialId } = await AndroidEmulatorUtils_1.AndroidEmulatorUtils.startAsync({
@@ -1 +1 @@
1
- {"version":3,"file":"startAndroidEmulator.js","sourceRoot":"","sources":["../../../src/steps/functions/startAndroidEmulator.ts"],"names":[],"mappings":"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","sourcesContent":["import { BuildFunction, BuildStepInput, BuildStepInputValueTypeName } from '@expo/steps';\nimport spawn from '@expo/turtle-spawn';\n\nimport { retryAsync } from '../../utils/retry';\nimport {\n AndroidDeviceName,\n AndroidEmulatorUtils,\n AndroidVirtualDeviceName,\n} from '../../utils/AndroidEmulatorUtils';\n\nexport function createStartAndroidEmulatorBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'start_android_emulator',\n name: 'Start Android Emulator',\n inputProviders: [\n BuildStepInput.createProvider({\n id: 'device_name',\n required: false,\n defaultValue: 'EasAndroidDevice01',\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'device_identifier',\n required: false,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'system_image_package',\n required: false,\n defaultValue: AndroidEmulatorUtils.defaultSystemImagePackage,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'count',\n required: false,\n defaultValue: 1,\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n }),\n ],\n fn: async ({ logger }, { inputs, env }) => {\n try {\n const availableDevices = await AndroidEmulatorUtils.getAvailableDevicesAsync({ env });\n logger.info(`Available Android devices:\\n- ${availableDevices.join(`\\n- `)}`);\n } catch (error) {\n logger.info('Failed to list available Android devices.', error);\n } finally {\n logger.info('');\n }\n\n const deviceName = `${inputs.device_name.value}` as AndroidVirtualDeviceName;\n const systemImagePackage = `${inputs.system_image_package.value}`;\n // We can cast because allowedValueTypeName validated this is a string.\n const deviceIdentifier = inputs.device_identifier.value as AndroidDeviceName | undefined;\n\n logger.info('Making sure system image is installed');\n await retryAsync(\n async () => {\n await spawn('sdkmanager', [systemImagePackage], {\n env,\n logger,\n });\n },\n {\n logger,\n retryOptions: {\n retries: 3, // Retry 3 times\n retryIntervalMs: 1_000,\n },\n }\n );\n\n logger.info('Creating emulator device');\n await AndroidEmulatorUtils.createAsync({\n deviceName,\n systemImagePackage,\n deviceIdentifier: deviceIdentifier ?? null,\n env,\n });\n\n logger.info('Starting emulator device');\n const { emulatorPromise, serialId } = await AndroidEmulatorUtils.startAsync({\n deviceName,\n env,\n });\n await AndroidEmulatorUtils.waitForReadyAsync({\n env,\n serialId,\n });\n logger.info(`${deviceName} is ready.`);\n\n const count = Number(inputs.count.value ?? 1);\n if (count > 1) {\n logger.info(`Requested ${count} emulators, shutting down ${deviceName} for cloning.`);\n await spawn('adb', ['-s', serialId, 'shell', 'reboot', '-p'], {\n logger,\n env,\n });\n // Waiting for source emulator to shutdown.\n await emulatorPromise;\n\n for (let i = 0; i < count; i++) {\n const cloneIdentifier = `eas-simulator-${i + 1}` as AndroidVirtualDeviceName;\n logger.info(`Cloning ${deviceName} to ${cloneIdentifier}...`);\n await AndroidEmulatorUtils.cloneAsync({\n sourceDeviceName: deviceName,\n destinationDeviceName: cloneIdentifier,\n env,\n });\n\n logger.info('Starting emulator device');\n const { serialId } = await AndroidEmulatorUtils.startAsync({\n deviceName: cloneIdentifier,\n env,\n });\n\n logger.info('Waiting for emulator to become ready');\n await AndroidEmulatorUtils.waitForReadyAsync({\n serialId,\n env,\n });\n\n logger.info(`${cloneIdentifier} is ready.`);\n }\n }\n },\n });\n}\n"]}
1
+ {"version":3,"file":"startAndroidEmulator.js","sourceRoot":"","sources":["../../../src/steps/functions/startAndroidEmulator.ts"],"names":[],"mappings":"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","sourcesContent":["import { BuildFunction, BuildStepInput, BuildStepInputValueTypeName } from '@expo/steps';\nimport spawn from '@expo/turtle-spawn';\nimport { asyncResult } from '@expo/results';\n\nimport { retryAsync } from '../../utils/retry';\nimport {\n AndroidDeviceName,\n AndroidEmulatorUtils,\n AndroidVirtualDeviceName,\n} from '../../utils/AndroidEmulatorUtils';\n\nexport function createStartAndroidEmulatorBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'start_android_emulator',\n name: 'Start Android Emulator',\n inputProviders: [\n BuildStepInput.createProvider({\n id: 'device_name',\n required: false,\n defaultValue: 'EasAndroidDevice01',\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'device_identifier',\n required: false,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'system_image_package',\n required: false,\n defaultValue: AndroidEmulatorUtils.defaultSystemImagePackage,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'count',\n required: false,\n defaultValue: 1,\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n }),\n ],\n fn: async ({ logger }, { inputs, env }) => {\n try {\n const availableDevices = await AndroidEmulatorUtils.getAvailableDevicesAsync({ env });\n logger.info(`Available Android devices:\\n- ${availableDevices.join(`\\n- `)}`);\n } catch (error) {\n logger.info('Failed to list available Android devices.', error);\n } finally {\n logger.info('');\n }\n\n const deviceName = `${inputs.device_name.value}` as AndroidVirtualDeviceName;\n const systemImagePackage = `${inputs.system_image_package.value}`;\n // We can cast because allowedValueTypeName validated this is a string.\n const deviceIdentifier = inputs.device_identifier.value as AndroidDeviceName | undefined;\n\n logger.info('Making sure system image is installed');\n await retryAsync(\n async () => {\n await spawn('sdkmanager', [systemImagePackage], {\n env,\n logger,\n });\n },\n {\n logger,\n retryOptions: {\n retries: 3, // Retry 3 times\n retryIntervalMs: 1_000,\n },\n }\n );\n\n logger.info('Creating emulator device');\n await AndroidEmulatorUtils.createAsync({\n deviceName,\n systemImagePackage,\n deviceIdentifier: deviceIdentifier ?? null,\n env,\n });\n\n logger.info('Starting emulator device');\n const { emulatorPromise, serialId } = await AndroidEmulatorUtils.startAsync({\n deviceName,\n env,\n });\n await AndroidEmulatorUtils.waitForReadyAsync({\n env,\n serialId,\n });\n logger.info(`${deviceName} is ready.`);\n\n const count = Number(inputs.count.value ?? 1);\n if (count > 1) {\n logger.info(`Requested ${count} emulators, shutting down ${deviceName} for cloning.`);\n await spawn('adb', ['-s', serialId, 'shell', 'reboot', '-p'], {\n logger,\n env,\n });\n // Waiting for source emulator to shutdown.\n // We don't care about resolved/rejected.\n await asyncResult(emulatorPromise);\n\n for (let i = 0; i < count; i++) {\n const cloneIdentifier = `eas-simulator-${i + 1}` as AndroidVirtualDeviceName;\n logger.info(`Cloning ${deviceName} to ${cloneIdentifier}...`);\n await AndroidEmulatorUtils.cloneAsync({\n sourceDeviceName: deviceName,\n destinationDeviceName: cloneIdentifier,\n env,\n logger,\n });\n\n logger.info('Starting emulator device');\n const { serialId } = await AndroidEmulatorUtils.startAsync({\n deviceName: cloneIdentifier,\n env,\n });\n\n logger.info('Waiting for emulator to become ready');\n await AndroidEmulatorUtils.waitForReadyAsync({\n serialId,\n env,\n });\n\n logger.info(`${cloneIdentifier} is ready.`);\n }\n }\n },\n });\n}\n"]}
@@ -1,4 +1,6 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="bunyan" />
3
+ import { bunyan } from '@expo/logger';
2
4
  import { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';
3
5
  import { z } from 'zod';
4
6
  /** Android Virtual Device is the device we run. */
@@ -27,10 +29,11 @@ export declare namespace AndroidEmulatorUtils {
27
29
  deviceIdentifier: AndroidDeviceName | null;
28
30
  env: NodeJS.ProcessEnv;
29
31
  }): Promise<void>;
30
- function cloneAsync({ sourceDeviceName, destinationDeviceName, env, }: {
32
+ function cloneAsync({ sourceDeviceName, destinationDeviceName, env, logger, }: {
31
33
  sourceDeviceName: AndroidVirtualDeviceName;
32
34
  destinationDeviceName: AndroidVirtualDeviceName;
33
35
  env: NodeJS.ProcessEnv;
36
+ logger: bunyan;
34
37
  }): Promise<void>;
35
38
  function startAsync({ deviceName, env, }: {
36
39
  deviceName: AndroidVirtualDeviceName;
@@ -9,8 +9,8 @@ const node_fs_1 = __importDefault(require("node:fs"));
9
9
  const node_os_1 = __importDefault(require("node:os"));
10
10
  const promises_1 = require("node:timers/promises");
11
11
  const node_path_1 = __importDefault(require("node:path"));
12
- // import { PipeMode } from '@expo/logger';
13
12
  const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
13
+ const fast_glob_1 = __importDefault(require("fast-glob"));
14
14
  const retry_1 = require("./retry");
15
15
  var AndroidEmulatorUtils;
16
16
  (function (AndroidEmulatorUtils) {
@@ -85,18 +85,32 @@ var AndroidEmulatorUtils;
85
85
  await avdManager;
86
86
  }
87
87
  AndroidEmulatorUtils.createAsync = createAsync;
88
- async function cloneAsync({ sourceDeviceName, destinationDeviceName, env, }) {
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
109
+ const lockfiles = await (0, fast_glob_1.default)('./**/*.lock', {
110
+ cwd: `${env.HOME}/.android/avd/${destinationDeviceName}.avd`,
111
+ absolute: true,
112
+ });
113
+ await Promise.all(lockfiles.map((lockfile) => node_fs_1.default.promises.rm(lockfile, { force: true })));
100
114
  const filesToReplaceDeviceNameIn = // TODO: Test whether we need to use `spawnAsync` here.
101
115
  (await (0, turtle_spawn_1.default)('grep', [
102
116
  '--binary-files=without-match',
@@ -108,10 +122,15 @@ var AndroidEmulatorUtils;
108
122
  .split('\n')
109
123
  .filter((file) => file !== '');
110
124
  for (const file of [...filesToReplaceDeviceNameIn, cloneIniFile]) {
111
- const txtFile = await node_fs_1.default.promises.readFile(file, 'utf-8');
112
- const replaceRegex = new RegExp(`${sourceDeviceName}`, 'g');
113
- const updatedTxtFile = txtFile.replace(replaceRegex, destinationDeviceName);
114
- await node_fs_1.default.promises.writeFile(file, updatedTxtFile);
125
+ try {
126
+ const txtFile = await node_fs_1.default.promises.readFile(file, 'utf-8');
127
+ const replaceRegex = new RegExp(`${sourceDeviceName}`, 'g');
128
+ const updatedTxtFile = txtFile.replace(replaceRegex, destinationDeviceName);
129
+ await node_fs_1.default.promises.writeFile(file, updatedTxtFile);
130
+ }
131
+ catch (err) {
132
+ logger.warn({ err }, `Failed to replace device name in ${file}.`);
133
+ }
115
134
  }
116
135
  }
117
136
  AndroidEmulatorUtils.cloneAsync = cloneAsync;
@@ -129,7 +148,11 @@ var AndroidEmulatorUtils;
129
148
  ], {
130
149
  detached: true,
131
150
  stdio: 'inherit',
132
- env,
151
+ env: {
152
+ ...env,
153
+ // We don't need to wait for emulator to exit gracefully.
154
+ ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL: '1',
155
+ },
133
156
  });
134
157
  // If emulator fails to start, throw its error.
135
158
  if (!emulatorPromise.child.pid) {
@@ -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\n// import { PipeMode } from '@expo/logger';\nimport spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';\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 }: {\n sourceDeviceName: AndroidVirtualDeviceName;\n destinationDeviceName: AndroidVirtualDeviceName;\n env: NodeJS.ProcessEnv;\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 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 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 }\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 }\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"]}
@@ -133,10 +133,6 @@ async function findAndParseFlowFilesAsync({ workingDirectory, dirPath, workspace
133
133
  // Determine flow patterns from config or use default
134
134
  const flowPatterns = (_a = workspaceConfig === null || workspaceConfig === void 0 ? void 0 : workspaceConfig.flows) !== null && _a !== void 0 ? _a : ['*'];
135
135
  logger.info(`Using flow patterns: ${JSON.stringify(flowPatterns)}`);
136
- logger.info(`Searching for flows with patterns: ${JSON.stringify(flowPatterns)}`, {
137
- cwd: dirPath,
138
- fg: flowPatterns,
139
- });
140
136
  // Use fast-glob to find matching files
141
137
  const matchedFiles = await (0, fast_glob_1.default)(flowPatterns, {
142
138
  cwd: dirPath,
@@ -1 +1 @@
1
- {"version":3,"file":"findMaestroPathsFlowsToExecuteAsync.js","sourceRoot":"","sources":["../../src/utils/findMaestroPathsFlowsToExecuteAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport * as path from 'node:path';\n\nimport { bunyan } from '@expo/logger';\nimport * as yaml from 'yaml';\nimport { z } from 'zod';\nimport { asyncResult } from '@expo/results';\nimport fg from 'fast-glob';\n\nconst FlowConfigSchema = z.object({\n name: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n\nconst WorkspaceConfigSchema = z.object({\n flows: z.array(z.string()).optional(),\n executionOrder: z.record(z.unknown()).optional(),\n includeTags: z.array(z.string()).optional(),\n excludeTags: z.array(z.string()).optional(),\n});\n\ntype FlowConfig = z.infer<typeof FlowConfigSchema>;\ntype WorkspaceConfig = z.infer<typeof WorkspaceConfigSchema>;\n\nexport async function findMaestroPathsFlowsToExecuteAsync({\n workingDirectory,\n flowPath,\n includeTags: _includeTags,\n excludeTags: _excludeTags,\n logger,\n}: {\n workingDirectory: string;\n flowPath: string;\n includeTags: string[] | undefined;\n excludeTags: string[] | undefined;\n logger: bunyan;\n}): Promise<string[]> {\n const absoluteFlowPath = path.resolve(workingDirectory, flowPath);\n // If it's a file, just return it (no validation needed)\n const stat = await fs.stat(absoluteFlowPath);\n\n if (stat.isFile()) {\n logger.info(`Found a file: ${path.relative(workingDirectory, absoluteFlowPath)}`);\n return [absoluteFlowPath];\n }\n\n // It's a directory - discover flow files\n logger.info(`Found a directory: ${path.relative(workingDirectory, absoluteFlowPath)}`);\n\n // Check for workspace config\n logger.info(`Searching for workspace config...`);\n const workspaceConfig = await findAndParseWorkspaceConfigAsync({\n dirPath: absoluteFlowPath,\n workingDirectory,\n logger,\n });\n logger.info(`Using workspace config: ${JSON.stringify(workspaceConfig)}`);\n\n if (workspaceConfig?.executionOrder) {\n logger.warn(`Execution order is not supported yet. Ignoring.`);\n }\n\n logger.info(`Searching for flow files...`);\n const { flows } = await findAndParseFlowFilesAsync({\n dirPath: absoluteFlowPath,\n workingDirectory,\n workspaceConfig,\n logger,\n });\n\n if (flows.length === 0) {\n logger.info(\n `No valid flow files found in: ${path.relative(workingDirectory, absoluteFlowPath)}`\n );\n return [];\n }\n\n const includeTags = [...(_includeTags ?? []), ...(workspaceConfig?.includeTags ?? [])];\n const excludeTags = [...(_excludeTags ?? []), ...(workspaceConfig?.excludeTags ?? [])];\n\n if (includeTags.length === 0 && excludeTags.length === 0) {\n logger.info(`No tags provided, returning all flows.`);\n return flows.map(({ path }) => path);\n }\n\n logger.info(\n `Filtering flows by tags. Tags to include: ${JSON.stringify(includeTags)}. Tags to exclude: ${JSON.stringify(excludeTags) ?? 'none'}.`\n );\n return flows\n .filter(({ config, path: flowPath }) => {\n const shouldInclude = matchesTags({\n flowTags: config?.tags ?? [],\n includeTags,\n excludeTags,\n });\n\n logger.info(\n shouldInclude\n ? `- ${path.relative(workingDirectory, flowPath)} matches tags, including.`\n : `- ${path.relative(workingDirectory, flowPath)} does not match tags, excluding.`\n );\n\n return shouldInclude;\n })\n .map(({ path }) => path);\n}\n\nasync function findAndParseWorkspaceConfigAsync({\n dirPath,\n workingDirectory,\n logger,\n}: {\n dirPath: string;\n workingDirectory: string;\n logger: bunyan;\n}): Promise<WorkspaceConfig | null> {\n const configPaths = await fg(['config.yaml', 'config.yml'], {\n cwd: dirPath,\n absolute: true,\n });\n\n if (configPaths.length === 0) {\n logger.info(`No workspace config found in: ${path.relative(workingDirectory, dirPath)}`);\n return null;\n }\n\n for (const configPath of configPaths) {\n try {\n const content = await fs.readFile(configPath, 'utf-8');\n const configDoc = yaml.parse(content);\n if (!configDoc) {\n logger.warn(\n `No content found in workspace config: ${path.relative(workingDirectory, configPath)}`\n );\n continue;\n }\n logger.info(`Using workspace config from: ${path.relative(workingDirectory, configPath)}`);\n return WorkspaceConfigSchema.parse(configDoc);\n } catch (err) {\n logger.warn(\n { err },\n `Failed to parse workspace config: ${path.relative(workingDirectory, configPath)}`\n );\n continue;\n }\n }\n\n logger.info(`No valid workspace config found in: ${path.relative(workingDirectory, dirPath)}`);\n return null;\n}\n\nasync function findAndParseFlowFilesAsync({\n workingDirectory,\n dirPath,\n workspaceConfig,\n logger,\n}: {\n workingDirectory: string;\n dirPath: string;\n workspaceConfig: WorkspaceConfig | null;\n logger: bunyan;\n}): Promise<{ flows: { config: FlowConfig; path: string }[] }> {\n const flows: { config: FlowConfig; path: string }[] = [];\n\n // Determine flow patterns from config or use default\n const flowPatterns = workspaceConfig?.flows ?? ['*'];\n logger.info(`Using flow patterns: ${JSON.stringify(flowPatterns)}`);\n\n logger.info(`Searching for flows with patterns: ${JSON.stringify(flowPatterns)}`, {\n cwd: dirPath,\n fg: flowPatterns,\n });\n\n // Use fast-glob to find matching files\n const matchedFiles = await fg(flowPatterns, {\n cwd: dirPath,\n absolute: true,\n onlyFiles: true,\n ignore: ['*/config.yaml', '*/config.yml'], // Skip workspace config files\n });\n\n logger.info(`Found ${matchedFiles.length} potential flow files`);\n\n // Parse each matched file\n for (const filePath of matchedFiles) {\n // Skip non-YAML files\n const ext = path.extname(filePath);\n if (ext !== '.yaml' && ext !== '.yml') {\n logger.info(`Skipping non-YAML file: ${path.relative(workingDirectory, filePath)}`);\n continue;\n }\n\n const result = await asyncResult(parseFlowFile(filePath));\n if (result.ok) {\n logger.info(`Found flow file: ${path.relative(workingDirectory, filePath)}`);\n flows.push({ config: result.value, path: filePath });\n } else {\n logger.info(\n { err: result.reason },\n `Skipping flow file: ${path.relative(workingDirectory, filePath)}`\n );\n }\n }\n\n return { flows };\n}\n\nasync function parseFlowFile(filePath: string): Promise<FlowConfig> {\n const content = await fs.readFile(filePath, 'utf-8');\n const documents = yaml.parseAllDocuments(content);\n const configDoc = documents[0];\n if (!configDoc) {\n throw new Error(`No config section found in ${filePath}`);\n }\n return FlowConfigSchema.parse(configDoc.toJS());\n}\n\nfunction matchesTags({\n flowTags,\n includeTags,\n excludeTags,\n}: {\n flowTags: string[];\n includeTags: string[];\n excludeTags: string[];\n}): boolean {\n // Include logic: if includeTags is empty OR flow has any of the include tags\n const includeMatch =\n includeTags.length === 0 || includeTags.some((tag) => flowTags.includes(tag));\n\n // Exclude logic: if excludeTags is empty OR flow has none of the exclude tags\n const excludeMatch =\n excludeTags.length === 0 || !excludeTags.some((tag) => flowTags.includes(tag));\n\n return includeMatch && excludeMatch;\n}\n"]}
1
+ {"version":3,"file":"findMaestroPathsFlowsToExecuteAsync.js","sourceRoot":"","sources":["../../src/utils/findMaestroPathsFlowsToExecuteAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport * as path from 'node:path';\n\nimport { bunyan } from '@expo/logger';\nimport * as yaml from 'yaml';\nimport { z } from 'zod';\nimport { asyncResult } from '@expo/results';\nimport fg from 'fast-glob';\n\nconst FlowConfigSchema = z.object({\n name: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n\nconst WorkspaceConfigSchema = z.object({\n flows: z.array(z.string()).optional(),\n executionOrder: z.record(z.unknown()).optional(),\n includeTags: z.array(z.string()).optional(),\n excludeTags: z.array(z.string()).optional(),\n});\n\ntype FlowConfig = z.infer<typeof FlowConfigSchema>;\ntype WorkspaceConfig = z.infer<typeof WorkspaceConfigSchema>;\n\nexport async function findMaestroPathsFlowsToExecuteAsync({\n workingDirectory,\n flowPath,\n includeTags: _includeTags,\n excludeTags: _excludeTags,\n logger,\n}: {\n workingDirectory: string;\n flowPath: string;\n includeTags: string[] | undefined;\n excludeTags: string[] | undefined;\n logger: bunyan;\n}): Promise<string[]> {\n const absoluteFlowPath = path.resolve(workingDirectory, flowPath);\n // If it's a file, just return it (no validation needed)\n const stat = await fs.stat(absoluteFlowPath);\n\n if (stat.isFile()) {\n logger.info(`Found a file: ${path.relative(workingDirectory, absoluteFlowPath)}`);\n return [absoluteFlowPath];\n }\n\n // It's a directory - discover flow files\n logger.info(`Found a directory: ${path.relative(workingDirectory, absoluteFlowPath)}`);\n\n // Check for workspace config\n logger.info(`Searching for workspace config...`);\n const workspaceConfig = await findAndParseWorkspaceConfigAsync({\n dirPath: absoluteFlowPath,\n workingDirectory,\n logger,\n });\n logger.info(`Using workspace config: ${JSON.stringify(workspaceConfig)}`);\n\n if (workspaceConfig?.executionOrder) {\n logger.warn(`Execution order is not supported yet. Ignoring.`);\n }\n\n logger.info(`Searching for flow files...`);\n const { flows } = await findAndParseFlowFilesAsync({\n dirPath: absoluteFlowPath,\n workingDirectory,\n workspaceConfig,\n logger,\n });\n\n if (flows.length === 0) {\n logger.info(\n `No valid flow files found in: ${path.relative(workingDirectory, absoluteFlowPath)}`\n );\n return [];\n }\n\n const includeTags = [...(_includeTags ?? []), ...(workspaceConfig?.includeTags ?? [])];\n const excludeTags = [...(_excludeTags ?? []), ...(workspaceConfig?.excludeTags ?? [])];\n\n if (includeTags.length === 0 && excludeTags.length === 0) {\n logger.info(`No tags provided, returning all flows.`);\n return flows.map(({ path }) => path);\n }\n\n logger.info(\n `Filtering flows by tags. Tags to include: ${JSON.stringify(includeTags)}. Tags to exclude: ${JSON.stringify(excludeTags) ?? 'none'}.`\n );\n return flows\n .filter(({ config, path: flowPath }) => {\n const shouldInclude = matchesTags({\n flowTags: config?.tags ?? [],\n includeTags,\n excludeTags,\n });\n\n logger.info(\n shouldInclude\n ? `- ${path.relative(workingDirectory, flowPath)} matches tags, including.`\n : `- ${path.relative(workingDirectory, flowPath)} does not match tags, excluding.`\n );\n\n return shouldInclude;\n })\n .map(({ path }) => path);\n}\n\nasync function findAndParseWorkspaceConfigAsync({\n dirPath,\n workingDirectory,\n logger,\n}: {\n dirPath: string;\n workingDirectory: string;\n logger: bunyan;\n}): Promise<WorkspaceConfig | null> {\n const configPaths = await fg(['config.yaml', 'config.yml'], {\n cwd: dirPath,\n absolute: true,\n });\n\n if (configPaths.length === 0) {\n logger.info(`No workspace config found in: ${path.relative(workingDirectory, dirPath)}`);\n return null;\n }\n\n for (const configPath of configPaths) {\n try {\n const content = await fs.readFile(configPath, 'utf-8');\n const configDoc = yaml.parse(content);\n if (!configDoc) {\n logger.warn(\n `No content found in workspace config: ${path.relative(workingDirectory, configPath)}`\n );\n continue;\n }\n logger.info(`Using workspace config from: ${path.relative(workingDirectory, configPath)}`);\n return WorkspaceConfigSchema.parse(configDoc);\n } catch (err) {\n logger.warn(\n { err },\n `Failed to parse workspace config: ${path.relative(workingDirectory, configPath)}`\n );\n continue;\n }\n }\n\n logger.info(`No valid workspace config found in: ${path.relative(workingDirectory, dirPath)}`);\n return null;\n}\n\nasync function findAndParseFlowFilesAsync({\n workingDirectory,\n dirPath,\n workspaceConfig,\n logger,\n}: {\n workingDirectory: string;\n dirPath: string;\n workspaceConfig: WorkspaceConfig | null;\n logger: bunyan;\n}): Promise<{ flows: { config: FlowConfig; path: string }[] }> {\n const flows: { config: FlowConfig; path: string }[] = [];\n\n // Determine flow patterns from config or use default\n const flowPatterns = workspaceConfig?.flows ?? ['*'];\n logger.info(`Using flow patterns: ${JSON.stringify(flowPatterns)}`);\n\n // Use fast-glob to find matching files\n const matchedFiles = await fg(flowPatterns, {\n cwd: dirPath,\n absolute: true,\n onlyFiles: true,\n ignore: ['*/config.yaml', '*/config.yml'], // Skip workspace config files\n });\n\n logger.info(`Found ${matchedFiles.length} potential flow files`);\n\n // Parse each matched file\n for (const filePath of matchedFiles) {\n // Skip non-YAML files\n const ext = path.extname(filePath);\n if (ext !== '.yaml' && ext !== '.yml') {\n logger.info(`Skipping non-YAML file: ${path.relative(workingDirectory, filePath)}`);\n continue;\n }\n\n const result = await asyncResult(parseFlowFile(filePath));\n if (result.ok) {\n logger.info(`Found flow file: ${path.relative(workingDirectory, filePath)}`);\n flows.push({ config: result.value, path: filePath });\n } else {\n logger.info(\n { err: result.reason },\n `Skipping flow file: ${path.relative(workingDirectory, filePath)}`\n );\n }\n }\n\n return { flows };\n}\n\nasync function parseFlowFile(filePath: string): Promise<FlowConfig> {\n const content = await fs.readFile(filePath, 'utf-8');\n const documents = yaml.parseAllDocuments(content);\n const configDoc = documents[0];\n if (!configDoc) {\n throw new Error(`No config section found in ${filePath}`);\n }\n return FlowConfigSchema.parse(configDoc.toJS());\n}\n\nfunction matchesTags({\n flowTags,\n includeTags,\n excludeTags,\n}: {\n flowTags: string[];\n includeTags: string[];\n excludeTags: string[];\n}): boolean {\n // Include logic: if includeTags is empty OR flow has any of the include tags\n const includeMatch =\n includeTags.length === 0 || includeTags.some((tag) => flowTags.includes(tag));\n\n // Exclude logic: if excludeTags is empty OR flow has none of the exclude tags\n const excludeMatch =\n excludeTags.length === 0 || !excludeTags.some((tag) => flowTags.includes(tag));\n\n return includeMatch && excludeMatch;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/build-tools",
3
- "version": "1.0.201",
3
+ "version": "1.0.203",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -79,5 +79,5 @@
79
79
  "node": "20.14.0",
80
80
  "yarn": "1.22.21"
81
81
  },
82
- "gitHead": "e21b7635fbf5b790298aab532f7968f5647718a5"
82
+ "gitHead": "4cbf585a25b6526fd718bcf66e20d0d65bc83f71"
83
83
  }