new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo · EAS · all subjects

build-reference/configuration

160 notes in this subject, read out of this brain and free to use. This is page 2 of 3.

EAS Build key features list

EAS Build key features include: cloud builds for Android and iOS with consistent environments, automatic provision and management of app signing credentials or use your own, shared internal distribution builds with a URL, automated builds with build profiles in eas.json (named sets of build settings) and integrations with EAS Workflows or CI pipelines, auto-submit successful builds to app stores via --auto-submit and EAS Submit, first-class expo-updates integration with per-profile channels and runtime version guidance, reuse of development builds across team (when two team members run eas build:dev and the project fingerprint matches, the existing build is downloaded from EAS instead of creating a new one), faster builds via dependency caching and custom cache paths, and install builds and updates on devices with Expo Orbit.

When to use EAS Build - recommended scenarios

EAS Build is recommended for: building production-ready binaries for app stores, sharing builds with testers via internal distribution, creating consistent builds across team members without local environment setup, automating builds from CI or EAS Workflows, and using managed app signing credentials. EAS Build is not recommended for debugging native code locally.

EAS Build with EAS Workflows example

EAS Build integrates with EAS Workflows using the build job type. Example configuration: jobs: build_ios: type: build params: platform: ios The build job supports builds for both platforms or conditional builds based on the branch: jobs: build: type: build params: platform: all profile: ${{ github.ref_name == 'main' && 'production' || 'preview' }} EAS Build also supports builds from GitHub and building on CI with any provider.

Orbit features - build and update management

Expo Orbit can install and launch builds from EAS on simulators and real devices in one click. It can also install and open updates from EAS on Android Emulators or iOS Simulators.

Orbit features - simulator management

Expo Orbit can list and launch simulators, including running Android emulators without audio. It can also launch Snack projects in simulators with one click.

Orbit features - local app installation

Expo Orbit supports installing and launching apps from local files using Finder or drag and drop. It supports Android .apk files, iOS Simulator compatible .app files, and ad hoc signed apps.

Orbit features - pinned projects

Expo Orbit displays pinned projects from the EAS dashboard and allows users to quickly launch their latest builds.

Orbit system requirements

Orbit relies on the Android SDK on macOS, Windows, and Linux. On macOS only, it requires xcrun for device management, which means both Android Studio and Xcode must be set up.

Orbit installation - Windows

On Windows, Expo Orbit can be downloaded directly from the GitHub releases page.

Build for both Android and iOS simultaneously

To create builds for both Android and iOS platforms at the same time, run the command eas build --platform all.

EAS Build function directory structure

The created EAS Build function module is located in the .eas/build directory and contains a package.json file with build scripts and a src directory with index.ts containing the function implementation. The build output generates build/index.js which must be uploaded as part of the project archive and not excluded by .gitignore or .easignore files.

Define EAS Build function in config.yml

Add a functions section to the config.yml file to expose custom functions. The functions block contains function definitions with properties: name (string), path (relative path from config file to function directory), inputs (optional array of input definitions with name and type), outputs (optional array of output definitions with name). Example: functions:\n my_function:\n name: My function\n path: ./myFunction\n inputs:\n - name: num1\n type: number\n - name: num2\n type: number\n outputs:\n - name: sum

Call EAS Build function in custom build config

To call a function in a config.yml build step, use the function name as a step. Functions can be invoked with inputs using the syntax: - my_function:\n inputs:\n num1: 1\n num2: 2\n id: sum_function. The id field is optional and allows referencing the function's outputs in subsequent steps using ${ steps.sum_function.outputName }.

EAS Build TypeScript function template structure

The default EAS Build function template imports BuildStepContext from '@expo/steps'. The function signature is: async function myFunction(ctx: BuildStepContext, { inputs, outputs, env }: { inputs: FunctionInputs; outputs: FunctionOutputs; env: BuildStepEnv; }): Promise<void>. Use ctx.logger.info() for logging. Define FunctionInputs and FunctionOutputs interfaces using BuildStepInput and BuildStepOutput types. Export the function as default export.

BuildStepInput and BuildStepOutput type definitions

Define function inputs using BuildStepInput<BuildStepInputValueTypeName.TYPE, required> where TYPE can be NUMBER, STRING, etc. The second parameter is a boolean indicating if the input is required. Define function outputs using BuildStepOutput<required> where the parameter is a boolean. Outputs must be strings, set values using outputs.outputName.set(stringValue).

EAS Build function example: sum calculator

Example TypeScript function that calculates sum of two numbers: import { BuildStepContext, BuildStepInput, BuildStepInputValueTypeName, BuildStepOutput, } from '@expo/steps'; interface FunctionInputs { num1: BuildStepInput<BuildStepInputValueTypeName.NUMBER, true>; num2: BuildStepInput<BuildStepInputValueTypeName.NUMBER, true>; } interface FunctionOutputs { sum: BuildStepOutput<true>; } async function myFunction( ctx: BuildStepContext, { inputs, outputs, }: { inputs: FunctionInputs; outputs: FunctionOutputs; } ): Promise<void> { ctx.logger.info(`num1: ${inputs.num1.value}`); ctx.logger.info(`num2: ${inputs.num2.value}`); const sum = inputs.num1.value + inputs.num2.value; ctx.logger.info(`sum: ${sum}`); outputs.sum.set(sum.toString()); } export default myFunction;

Custom build config file location and name

Create a custom build config file at .eas/build/ directory at the same level as eas.json. The file must have a .yml extension. The filename itself can be anything (for example, hello-world.yml or test.yml), but the directory structure and .yml extension are required for EAS Build to identify the custom build config.

Custom build config YAML structure

A custom build config YAML file contains a top-level 'build' key with 'name' and 'steps' properties. The 'name' field provides a descriptive title for the build. The 'steps' array contains build commands, where each step can use 'run' to execute shell commands or call built-in EAS functions.

Custom build config example with echo command

The following example shows a basic custom build config that runs an echo command: ```yaml build: name: Hello World! steps: - run: echo "Hello, world!" ``` This config defines a build step that executes the shell command 'echo "Hello, world!"'.

Verify custom build execution in logs

After a custom build completes, verify that the build steps were executed by checking the logs on the build's detail page in the EAS dashboard.

build section structure and requirements

The build section describes a custom build configuration. All config options to create a custom build are specified under it. It requires at least one step to be defined per build.

steps[].run property for shell commands

The run key is used to trigger a set of instructions. It can execute single or multiline shell commands. A run step can have properties: name (displayed in build logs), command (required, the shell command to run), working_directory (existing directory path from project root), shell (default executable shell), inputs (input values provided to the step), and outputs (output values expected from the step).

steps[].run.id property for output reuse

Defining an id for a step allows calling the same function that produces one or more outputs multiple times and using the output from one step to another. Steps with ids can have their outputs accessed in other steps using the syntax ${ steps.[step_id].[output_name] }.

functions section for reusable functions

The functions section is used to describe reusable functions that can be used in a build config. All config options to create a function are specified with properties: functions.[function_name] (the name of the function), name (display name in build logs), inputs (input values provided to the function), outputs (output values expected from the function), command (shell command to run, if simple script) or path (path to JS/TS module implementing the function), shell (default executable shell), and supported_platforms (supported platforms, defaults to all).

functions.[function_name].inputs structure

Input values for a function are defined as an array with the following properties per input: name (identifier for the input), required (boolean, defaults to true if not specified), type (string, num, or json, defaults to string), default_value (default input value), and allowed_values (array of multiple allowed values for validation).

functions.[function_name].outputs structure

Output values for a function can be specified as a simple array of output names or as an array of objects with properties: name (identifier for the output) and required (boolean to indicate if output is required).

import section for importing functions

The import section is a config file path list used to import functions from other config files. Imported files cannot have the build section. Functions from imported files can be called directly in the steps by their function name.

eas/checkout function with ref input

The eas/checkout function checks out project source files. For builds with Git-based project sources, it uses the build's recorded commit by default. Use ref input to check out a different branch, tag, or commit. ref accepts a branch (bare name or qualified ref), a tag (qualified ref), or a full commit SHA. The ref input only works when project sources come from a Git repository and must be placed before eas/build.

eas/build known limitations

The eas/build function has the following limitations: it doesn't accept any inputs, and the resolved build process will be configured based on the build profile from eas.json. The build process produced by eas/build is not configurable and cannot be customized. To customize the build process, use the subset of functions and steps that are executed behind the scenes by eas/build.

eas/find_and_upload_build_artifacts step

The eas/find_and_upload_build_artifacts step automatically finds and uploads application archives, additional build artifacts, and Xcode logs from default locations and using buildArtifactPaths configuration. It uploads found artifacts to the EAS servers. This step can be used for both iOS and Android builds. Source code is available at https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/functions/findAndUploadBuildArtifacts.ts

PostHog integration functions for EAS Workflows

Several PostHog functions are available for EAS Workflows: eas/posthog_capture_event sends analytics events to mark builds and milestones, eas/posthog_flag_rollout enables/disables or rolls out feature flags by key, eas/posthog_wait_for_metric pauses until a HogQL query returns a number satisfying a comparison, eas/posthog_wait_for_query pauses until a HogQL query returns true, eas/posthog_annotation creates timeline annotations, and eas/posthog_upload_sourcemaps uploads JavaScript source maps for error tracking. Run 'eas integrations:posthog:connect' to link a PostHog project. eas/posthog_capture_event uses your public project API key, while other functions use a PostHog personal API key with specific scopes.

eas/posthog_wait_for_metric has no ignore_error input

The eas/posthog_wait_for_metric step has no ignore_error input. A timeout or an unreadable query always fails the step. The step runs a HogQL query every interval_seconds until the comparison is true or timeout_seconds elapses.

eas/posthog_wait_for_query step behavior

The eas/posthog_wait_for_query step pauses until a HogQL query returns true. It has no ignore_error input, and a timeout or unreadable query always fails the step. The step clears when the first column of the first row is true or a nonzero number.

Reusable functions in custom build YAML

You can define reusable functions in custom build YAML with a functions section. Each function can have a name, parameter list with default values, inputs array, and a command. Reusable functions can be called in build.steps by name with inputs provided. Multiple reusable functions can be executed sequentially in build.steps.

Example: eas/posthog_flag_rollout step

Example of rolling out a PostHog feature flag to 25 percent: eas/posthog_flag_rollout with inputs flag: 'new-checkout' and rollout_percentage: 25. Provide at least one of active, rollout_percentage, or payload inputs.

Example: eas/posthog_wait_for_metric step

Example of gating a build on error count: eas/posthog_wait_for_metric with inputs query: 'SELECT count() FROM events WHERE event = '$exception' AND timestamp > now() - INTERVAL 15 MINUTE', operator: 'lt', threshold: 10. This pauses until error count over 15 minutes is less than 10.

Use Expo Atlas to analyze JavaScript bundle size

To analyze JavaScript bundles and understand their impact on app size, use Expo Atlas. This tool can help identify libraries that have a larger impact than expected and detect unused libraries.

Asset selection in SDK 52 and later

For SDK 52 and later, include the property `updates.assetPatternsToBeBundled` in your app config. It should define one or more file-matching patterns using regular expressions. Example: `"updates": { "assetPatternsToBeBundled": ["app/images/**/*.png"] }` will include all .png files in all subdirectories of app/images in updates.

app.json runtime version appVersion example

To configure runtime version with appVersion policy, add this to app.json: { 'expo': { 'runtimeVersion': { 'policy': 'appVersion' } } }

EAS CLI command: eas env:pull

Use eas env:pull --environment environment-name to download environment variables into a .env file for local development. Secret variables are not available for reading through this command. The created .env file should be kept in .gitignore to avoid leaks and precedence conflicts between local and cloud jobs.

Using app config with GOOGLE_SERVICES_JSON secret file

Secret file variables like GOOGLE_SERVICES_JSON are not readable outside EAS servers and are used to provide files to EAS Build jobs. To use them in app config, reference process.env and provide a fallback value for local development: googleServicesFile: process.env.GOOGLE_SERVICES_JSON ?? '/local/path/to/google-services.json'

Example: Using EXPO_PUBLIC_API_URL in client code

Environment variables with EXPO_PUBLIC_ prefix can be accessed in app code via process.env. Example: const apiUrl = process.env.EXPO_PUBLIC_API_URL; can be used to dynamically configure API endpoints for fetch requests.

Example: Using environment variables in app.config.js

Non-prefixed environment variables can be used in app.config.js to configure app properties based on variants. Example: const IS_DEV = process.env.APP_VARIANT === 'development'; can determine bundle identifiers and app names for different variants.

EAS CLI command: eas env:list

Use eas env:list to verify environment variables that are set. The command accepts --environment parameter to filter by a specific environment.

Default environments available

Three environments are available by default: development, preview, and production. A variable can be reused across all environments or customized per environment.

EAS CLI command: eas env:set

Use eas env:set to add or update environment variables. The command requires --name, --value, --environment, and --visibility parameters. Example: eas env:set --name EXPO_PUBLIC_API_URL --value https://example.app/staging --environment preview --visibility plaintext

Set environment explicitly in workflow jobs

Set the environment field explicitly on a job to override its default and keep it in sync with the build profile used earlier in the workflow. This ensures consistent environment variables are used across dependent jobs.

External content in store config

Store config JavaScript files can fetch external content from services, including through async functions. The function results are awaited before validating and syncing with the stores. Environment variables can be used for special values like secrets.

Static store config JSON format

The default store config type for EAS Metadata is a JSON file. A basic example includes configVersion set to 0, and an apple object containing info with language keys (like en-US) that specify title, subtitle, description, keywords, marketingUrl, supportUrl, and privacyPolicyUrl.

Store config schema validation

All configuration options for store.config.json are documented in the store config schema. The VS Code Expo Tools extension provides auto-complete, suggestions, and warnings for store.config.json files.

Dynamic store config with JavaScript

EAS Metadata supports dynamic config using JavaScript files named store.config.js. The file can export a plain object or a synchronous or asynchronous function. This allows for dynamic values such as current year in copyright notices, and the metadataPath property in eas.json must point to the JavaScript file.

Store config async function example

When exporting an async function from store.config.js, the function can fetch external localizations and return modified config. Example: module.exports = async () => { const year = new Date().getFullYear(); const info = await fetchLocalizations('...').then(response => response.json()); config.apple.copyright = `${year} Acme, Inc.`; config.apple.info = info; return config; };

Store config JavaScript with static data import

Dynamic store.config.js can require the JSON file generated by eas metadata:pull. Example: const config = require('./store.config.json'); const year = new Date().getFullYear(); config.apple.copyright = `${year} Acme, Inc.`; module.exports = config;

Regenerate native directories when switching app variants locally

APP_VARIANT changes only the app's name and package name on Android and bundle identifier on iOS; it does not affect how the binary is compiled. When switching variants, the existing android and ios directories still reflect the previous variant. To switch variants, regenerate the native directories with prebuild --clean before compiling. Set APP_VARIANT on both the prebuild and run commands so they use the same variant. For example: APP_VARIANT=test npx expo prebuild --clean, then APP_VARIANT=test npx expo run:ios.

GitHub builds require prior successful local build

Before triggering EAS builds from a GitHub repository, you must first configure your project for EAS Build and successfully run a build from your local computer for each platform you want to support on GitHub. This means running eas build -p [all|ios|android] successfully before attempting GitHub-triggered builds.

GitHub account linking requirements for GitHub builds

To trigger builds from GitHub, an Expo user in your organization must have a linked GitHub user account with access to the target repository. Verify the GitHub account is linked in Account settings > Overview > User settings > Connections. Additionally, you must accept the permissions requested by the Expo GitHub app at https://github.com/settings/installations.

GitHub organization repositories require Expo organization

You can only link GitHub organization repositories to Expo organizations. If you need to link a repository from a different GitHub account, use the 'Add new account' option in the account selector dropdown on the project GitHub settings page.

Base directory configuration for GitHub monorepo projects

If your Expo project source code is in a subdirectory of your repository (monorepo setup), you must configure the 'Base directory' setting on your project's GitHub settings page at https://expo.dev/accounts/[account]/projects/[projectName]/github. If the Expo project is in the repository root, no configuration is needed.

GitHub PR build uses latest commit on base branch

When a build is triggered from a GitHub PR using a label, the build runs against the latest commit on the PR's base branch, not the PR's head branch. Build status appears in the PR's checks section with a link to the build details.

EAS Workflows for automatic builds on push

To automatically build your Expo project when code is pushed to GitHub, use EAS Workflows. Create a .eas/workflows/build.yml file with job configuration. Example: A workflow with on.push.branches set to [main] and jobs.build_android and jobs.build_ios with type: build and platform parameters will trigger Android and iOS builds on every push to main. See EAS Workflows documentation at /eas/workflows/get-started for more configuration options.

Give your agent this brain