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

eas-workflows

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

Maestro flow file structure for launchApp and assertions

A Maestro flow YAML file starts with an appId field containing the app's bundle identifier. Following the appId, a '---' separator begins the flow commands. Commands include: launchApp to launch the application, assertVisible to assert text is visible on screen, and tapOn to tap on UI elements. Example: appId: dev.expo.eastestsexample followed by --- and command list.

EAS Workflows E2E test workflow with Maestro job

An E2E test workflow YAML file under .eas/workflows defines a 'build' type job to compile the app and a 'maestro' type job that depends on the build output. The maestro job uses build_id from the build job's output and specifies flow_path as a list of .maestro flow file paths to execute. Example structure for Android: name: e2e-test-android on: pull_request: branches: ['*'] jobs: build_android_for_e2e: type: build params: platform: android profile: e2e-test maestro_test: needs: [build_android_for_e2e] type: maestro params: build_id: ${{ needs.build_android_for_e2e.outputs.build_id }} flow_path: ['.maestro/home.yml', '.maestro/expand_test.yml']

EAS Workflows directory structure

EAS Workflows are stored in a .eas/workflows directory at the root of the project. Workflow files are YAML files with descriptive names such as e2e-test-android.yml and e2e-test-ios.yml.

Maestro test flow with UI interaction and assertions

A Maestro flow can combine launch, interaction, and assertion commands. Example flow: appId: dev.expo.eastestsexample --- - launchApp - tapOn: 'Explore.*' - tapOn: '.*File-based routing' - assertVisible: 'This app has two screens.*' This flow launches the app, taps on the Explore tab, taps on the File-based routing section, and asserts that the text 'This app has two screens.' appears.

E2E test workflow for iOS platform

Create an iOS E2E test workflow similar to Android. The build job specifies platform: ios and profile: e2e-test. The maestro job receives the build_id from the iOS build and runs the same Maestro flows. Example: name: e2e-test-ios on: pull_request: branches: ['*'] jobs: build_ios_for_e2e: type: build params: platform: ios profile: e2e-test maestro_test: needs: [build_ios_for_e2e] type: maestro params: build_id: ${{ needs.build_ios_for_e2e.outputs.build_id }} flow_path: ['.maestro/home.yml', '.maestro/expand_test.yml']

E2E test workflow automation with pull_request trigger

EAS Workflows can be triggered automatically by configuring the 'on' section with 'pull_request' trigger. Setting branches to ['*'] runs the workflow on every pull request to any branch. This allows E2E tests to run automatically when pull requests are opened without manual invocation.

Run E2E test workflow manually with EAS CLI

Execute an E2E test workflow manually using the command: eas workflow:run .eas/workflows/e2e-test-android.yml, replacing the filename with the appropriate workflow file path.

Basic preview update workflow YAML structure

A basic EAS workflow file for publishing preview updates on every commit is stored at .eas/workflows/publish-preview-update.yml. The workflow has the structure: name: 'Publish preview update', on: push with branches filter set to ['*'], jobs with a single job 'publish_preview_update' having name 'Publish preview update', type 'update', and params with branch set to '${{ github.ref_name || 'test' }}'.

Preview updates workflow for team review

Preview updates allow you to share changes with your team for review without requiring them to pull the latest changes and run them locally. You can access preview updates in the development build UI and through scannable QR codes on the EAS dashboard. This is particularly useful when publishing previews on every commit, enabling team members to review changes without pulling code locally.

Create production builds for app stores

Use eas workflow:create --template deploy to generate a release workflow that configures EAS Build and EAS Update, sets app identifiers, and writes the workflow to .eas/workflows/deploy.yml. This workflow fingerprints the project, builds and submits a production build when there are native changes, or publishes an over-the-air update when a matching build exists.

Install development builds to emulator and simulator

Use eas build:run -p android --latest to install the latest build on Android Emulator and eas build:run -p ios -e development-ios-simulator --latest to install on iOS Simulator. Then run npx expo start to start the development server.

Run an EAS workflow

Run eas workflow:run .eas/workflows/build.yml to execute a workflow. The workflow can be monitored on the project's workflows page in the Expo dashboard.

Create development build workflow with template

Run eas workflow:create --template build to generate a workflow file at .eas/workflows/build.yml that creates development builds for Android and iOS.

Workflow file location and generation

Workflow files are stored in the .eas/workflows directory with .yml extension. The eas workflow:create command with --template option generates workflow files in this directory and sets up the project for building or deployment.

Trigger workflows with GitHub pushes

Add an 'on' trigger to the workflow YAML file to trigger workflows on GitHub events. For example, to trigger on pushes to the main branch, add 'on: push: branches: [main]' at the top level of the workflow file.

Trigger workflows from App Store Connect events

Configure App Store Connect connection in EAS dashboard by navigating to Project settings > General > Connections and connecting the App Store Connect app. Then use on.app_store_connect in the workflow file to trigger on App Store Connect events such as ready_for_review or waiting_for_review app version states.

Link GitHub repository to EAS project

Navigate to the project's GitHub settings in the Expo dashboard, install the GitHub app, and select the GitHub repository that matches the Expo project to connect it.

EAS Workflows overview and first steps

EAS Workflows automate React Native CI/CD development and release processes. To get started, sign up for an Expo account, create a project with create-expo-app using template default@sdk-57, and install EAS CLI globally with npm install -g eas-cli.

EAS Workflows cloud machine types

Workflows run on EAS's managed infrastructure with the following machine types: Linux workers including linux-medium (4 vCPU, 16 GB RAM) and linux-large (8 vCPU, 32 GB RAM); Linux with nested virtualization for Android emulators including linux-medium-nested-virtualization and linux-large-nested-virtualization; and macOS workers for iOS builds and simulators including macos-medium (5 cores, 20 GB RAM) and macos-large (10 cores, 40 GB RAM).

Manual workflow execution without GitHub

Any workflow can be run manually using eas workflow:run regardless of the on trigger configuration, allowing workflows to be triggered without GitHub integration.

When to use EAS Workflows

EAS Workflows is recommended for automating builds, app store submissions, over-the-air updates, and web deployments; deploying web apps to EAS Hosting; running E2E tests with Maestro as part of CI; triggering builds and updates from GitHub push or pull request events; and achieving CI/CD without managing your own infrastructure or macOS machines. EAS Workflows is not recommended for highly customized pipelines that depend on non-EAS services like Docker or custom runners.

EAS Workflows current limitations

EAS Workflows currently has the following limitations: no shared workflow configurations (each workflow must be defined independently), and no matrix builds (cannot run multiple variations with different configurations in parallel).

EAS Workflows compatibility with React Native projects

EAS Workflows works with both CNG (Continuous Native Generation) projects and existing React Native projects, as long as the project is configured for EAS Build.

Custom jobs and scripts in workflows

Custom jobs with steps let you run shell commands, use built-in functions like eas/checkout and eas/install_node_modules, and set outputs for downstream jobs.

Parallel job execution in workflows

Jobs without dependencies run in parallel by default. Use the 'needs' keyword to specify that a job should wait for another job to succeed, or 'after' to wait for a job to complete regardless of success or failure.

EAS Workflows overview and purpose

EAS Workflows is a CI/CD service from EAS (Expo Application Services) that automates repeated tasks like building Android and iOS binaries, publishing over-the-air updates, submitting to app stores, running E2E tests, and deploying web apps to EAS Hosting. Workflows run in managed cloud environments with pre-packaged job types designed specifically for mobile app development.

EAS Workflows key features

EAS Workflows includes the following features: pre-packaged jobs that build, submit, and update apps, run Maestro E2E tests, and send Slack messages; flexible triggers on GitHub events, cron schedules, App Store Connect events, manual runs via eas workflow:run, or REST API; managed macOS and Linux workers requiring no infrastructure maintenance; a single dashboard on expo.dev showing builds, updates, test results, artifacts, and logs; and faster releases using fingerprint, get-build, and update jobs to skip redundant native builds and publish over-the-air updates.

Workflow file location and structure

Workflows are defined as YAML files in the .eas/workflows/ directory at the root of your project. Each file specifies a name, optional triggers (on), and one or more jobs that run in the cloud.

Create first workflow with EAS CLI

To create your first workflow, run the command 'eas workflow:create' and follow the prompts.

EAS Workflows triggers and execution

When an EAS project is linked to GitHub, teams can trigger workflows from GitHub events (push, pull request, labels) or schedules (cron), or run them manually via the EAS CLI. Workflows can also be triggered using the REST API or from App Store Connect events.

POST /v2/workflows/dispatch request body schema

The request body for POST /v2/workflows/dispatch has the following fields: appId (string UUID, required) - The EAS project ID found on the project page or in app config under extra.eas.projectId. gitRef (string, required) - A branch name (main), tag (v1.0.0), commit SHA, or fully qualified ref (refs/heads/main, refs/tags/v1.0.0). fileName (string, required) - The workflow file name only, such as deploy.yml; do not include the .eas/workflows/ prefix or any other path segments. inputs (object, optional) - Values for inputs declared under on.workflow_dispatch.inputs in the workflow file, validated against the declared schema.

Trigger workflow endpoint POST /v2/workflows/dispatch

POST /v2/workflows/dispatch resolves the workflow file on the given Git ref, validates inputs against the workflow_dispatch schema declared in the workflow, and enqueues a new run.

Robot users for production EAS integrations

For production integrations with the EAS REST API, create a robot user on the account that owns the project and give it a scoped role. The token then represents the robot user, not a person. You can revoke it without affecting any user. A personal access token also works for one-off scripts.

EAS REST API authentication header

Both EAS REST API endpoints require an EAS access token sent as a bearer token in the Authorization header. The header format is: Authorization: Bearer <EXPO_TOKEN>. Content-Type must be application/json.

EAS REST API base URL

All EAS REST API endpoints live under https://api.expo.dev. Requests and responses are JSON.

POST /v2/workflows/dispatch response

Returns 200 OK with a JSON response containing data.id (the new workflow run ID as UUID) and data.url (a link to the run in the dashboard).

GET /v2/workflows/runs/:workflowRunId error responses

GET /v2/workflows/runs/:workflowRunId returns: 400 if workflowRunId is not a valid UUID. 403 if the token does not have access to the run's project. 404 if no workflow run exists with that ID.

Poll workflow run until completion shell script example

RUN_ID=$(curl -s -X POST "https://api.expo.dev/v2/workflows/dispatch" \ -H "Authorization: Bearer $EXPO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"appId":"...","gitRef":"main","fileName":"deploy.yml"}' \ | jq -r '.data.id') while true; do STATUS=$(curl -s "https://api.expo.dev/v2/workflows/runs/$RUN_ID" \ -H "Authorization: Bearer $EXPO_TOKEN" \ | jq -r '.data.status') echo "status: $STATUS" case "$STATUS" in success|failure|canceled) break ;; esac sleep 10 done

GET /v2/workflows/runs/:workflowRunId response example

A successful response includes id (the workflow run ID), status (the run status), url (the dashboard link), gitCommitHash, gitCommitMessage, requestedGitRef, triggerEventType, createdAt, updatedAt, and jobs (array of job objects, each with id, key, name, type, status, requiredJobKeys, environment, outputs, errors, buildId, submissionId, createdAt, updatedAt).

Workflow job outputs and IDs

The outputs field in a job response contains any values the job sets with outputs: in the workflow file. Any referenced secrets appear as placeholders in the response. Jobs of type: build include buildId, and jobs of type: submission include submissionId. Each ID links to the underlying EAS Build or EAS Submit record.

Workflow job status values

Each job in a workflow run has a status, one of: new (the job is queued), in-progress (the job is running), action-required (the job is paused and waiting on a manual action such as approval), pending-cancel (a cancellation has been requested but the job has not stopped yet), success (the job succeeded; terminal state), failure (the job failed; terminal state), canceled (the job was canceled; terminal state), skipped (the job was skipped because a required upstream job did not succeed).

Get workflow run endpoint GET /v2/workflows/runs/:workflowRunId

GET /v2/workflows/runs/:workflowRunId returns the workflow run and the jobs it contains. Use this endpoint to poll for completion after triggering a run, or to render a run's details in your own UI.

POST /v2/workflows/dispatch error responses

POST /v2/workflows/dispatch returns: 400 if the request body fails schema validation or inputs do not match the workflow's declared schema. 403 if the token does not have access to the given appId. 404 if the Git ref does not exist in the linked repository or the workflow file is not found on that ref.

POST /v2/workflows/dispatch curl example

curl -X POST "https://api.expo.dev/v2/workflows/dispatch" \ -H "Authorization: Bearer $EXPO_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "appId": "a415eac6-231a-4b38-b481-3255a59f13b8", "gitRef": "main", "fileName": "deploy.yml", "inputs": { "environment": "production" } }'

EAS Workflows testflight job example

Example EAS Workflows configuration for TestFlight distribution in .eas/workflows/testflight.yml: ```yaml jobs: build_ios: name: Build iOS type: build params: platform: ios profile: production testflight: name: Distribute to TestFlight type: testflight needs: [build_ios] params: build_id: ${{ needs.build_ios.outputs.build_id }} internal_groups: ['QA Team'] external_groups: ['Public Beta'] changelog: | What's new in this release: - New features - Bug fixes ``` This workflow builds an iOS app and then distributes it to TestFlight internal and external groups with changelog notes.

EAS Workflows testflight job for TestFlight automation

You can automate distributing a build to external groups with the pre-packaged 'testflight' job in EAS Workflows. It adds a build to internal and external groups, sets the 'What to Test' notes, and submits for Beta App Review. The 'submit_beta_review' parameter defaults to true when 'external_groups' is provided.

Update job type syntax and parameters

The update job type publishes an update using EAS Update. Its syntax is: ```yaml jobs: publish_update: type: update environment: production | preview | development # optional, defaults to production env: # optional list of environment variables ENV_VAR_NAME: value params: message: string # optional platform: string # optional - android | ios | all, defaults to all branch: string # optional channel: string # optional - cannot be used with branch rollout_percentage: number # optional - 0 to 100, defaults to 100 private_key_path: string # optional upload_sentry_sourcemaps: boolean # optional - defaults to "try uploading, but don't fail the job if it fails" hooks: after_checkout: step[] # optional before_install_node_modules: step[] # optional after_install_node_modules: step[] # optional before_update: step[] # optional after_update: step[] # optional ``` Parameters: - message (optional, string): Message to use for the update. If not provided, the commit message will be used. - platform (optional, string): Platform to use for the update, either 'android', 'ios', or 'all'. Defaults to 'all'. - branch (optional, string): Branch to use for the update. If not provided, the branch from the workflow run will be used. - channel (optional, string): Channel to use for the update. Provide either a branch or a channel, not both. - rollout_percentage (optional, number): Percentage of users this update should be immediately available to. Must be an integer between 0 and 100. - private_key_path (optional, string): Path to the file containing the PEM-encoded private key for code signing. - upload_sentry_sourcemaps (optional, boolean): Whether to upload Sentry sourcemaps. If not provided, the job checks if @sentry/react-native is installed and tries to upload if it is.

TestFlight job outputs

The TestFlight job produces the following outputs that can be referenced in subsequent jobs: For build_id variant: - apple_app_id (string): The Apple App ID of the submitted build. - ios_bundle_identifier (string): The iOS bundle identifier of the submitted build. For asc_build_id variant: - asc_build_id (string): The App Store Connect build ID. - apple_app_id (string): The Apple App ID of the submitted build. - ios_bundle_identifier (string): The iOS bundle identifier of the submitted build.

TestFlight job type syntax for submitting an already uploaded build

The TestFlight job type with asc_build_id (submitting an already uploaded build) has the following syntax: ```yaml jobs: testflight_distribution: type: testflight params: asc_build_id: string # required internal_groups: string[] # optional external_groups: string[] # optional changelog: string # optional submit_beta_review: boolean # optional ``` Parameters: - asc_build_id (required, string): The ID of a build that already exists in App Store Connect. - internal_groups (optional, string[]): An array of TestFlight internal group names to add the build to. - external_groups (optional, string[]): An array of TestFlight external group names to add the build to. - changelog (optional, string): Test notes ('What to Test') for TestFlight testers. - submit_beta_review (optional, boolean): Whether to submit for Beta App Review.

TestFlight job type syntax for uploading a build

The TestFlight job type with build_id (uploading and submitting a build) has the following syntax: ```yaml jobs: testflight_distribution: type: testflight params: build_id: string # required profile: string # optional - default: production internal_groups: string[] # optional external_groups: string[] # optional changelog: string # optional submit_beta_review: boolean # optional wait_processing_timeout_seconds: number # optional - default: 1800 (30 minutes) hooks: after_checkout: step[] # optional before_install_node_modules: step[] # optional after_install_node_modules: step[] # optional ``` Parameters: - build_id (required, string): The ID of the iOS EAS Build to distribute. - profile (optional, string): The submit profile to use. Defaults to 'production'. - internal_groups (optional, string[]): An array of TestFlight internal group names to add the build to. Only include groups without automatic distribution enabled. - external_groups (optional, string[]): An array of TestFlight external group names to add the build to. - changelog (optional, string): Test notes ('What to Test') for TestFlight testers. - submit_beta_review (optional, boolean): Whether to submit for Beta App Review. If not specified, defaults to true when external_groups are provided, false otherwise. - wait_processing_timeout_seconds (optional, number): Timeout in seconds to wait for App Store Connect build processing. Defaults to 1800 (30 minutes). Only applies when distributing via groups or changelog.

Submit job outputs

The submit job produces the following outputs that can be referenced in subsequent jobs: - apple_app_id (string): The Apple App ID of the submitted build. - ios_bundle_identifier (string): The iOS bundle identifier of the submitted build. - android_package_id (string): The Android package ID of the submitted build.

Submit job type syntax and parameters

The submit job type submits an Android or iOS build to the app store. Its syntax is: ```yaml jobs: submit_to_store: type: submit params: build_id: string # required profile: string # optional - default: production groups: string[] # optional hooks: after_checkout: step[] # optional before_install_node_modules: step[] # optional after_install_node_modules: step[] # optional before_submit: step[] # optional after_submit: step[] # optional ``` Parameters: - build_id (required, string): The ID of the build to submit. - profile (optional, string): The submit profile to use. Defaults to 'production'. - groups (optional, string[]): TestFlight internal group names to add the build to. For more TestFlight distribution options, see the TestFlight job.

Get-build job outputs

The get-build job produces the following outputs that can be referenced in subsequent jobs: - build_id (string): The ID of the retrieved build. - app_build_version (string): The build version of the app. - app_identifier (string): The bundle identifier/package name of the app. - app_version (string): The version of the app. - channel (string): The update channel used for the build. - distribution (string): The distribution method used. - fingerprint_hash (string): The fingerprint hash of the build. - git_commit_hash (string): The git commit hash used for the build. - platform (string): The platform the build was created for. - profile (string): The build profile used. - runtime_version (string): The runtime version used. - sdk_version (string): The SDK version used. - simulator (string): Whether the build is for simulator.

Get-build job type

The get-build job type retrieves an existing build from EAS that matches the provided parameters. Its syntax is: ```yaml jobs: get_build: type: get-build params: platform: ios | android # optional profile: string # optional distribution: store | internal | simulator # optional channel: string # optional app_identifier: string # optional app_build_version: string # optional app_version: string # optional git_commit_hash: string # optional fingerprint_hash: string # optional sdk_version: string # optional runtime_version: string # optional simulator: boolean # optional wait_for_in_progress: boolean # optional ``` Parameters: - platform (optional, string): The platform to get the build for, either 'ios' or 'android'. - profile (optional, string): The build profile to use. - distribution (optional, string): The distribution method, either 'store', 'internal', or 'simulator'. - channel (optional, string): The update channel. - app_identifier (optional, string): The bundle identifier/package name. - app_build_version (optional, string): The build version. - app_version (optional, string): The app version. - git_commit_hash (optional, string): The git commit hash. - fingerprint_hash (optional, string): The fingerprint hash. - sdk_version (optional, string): The SDK version. - runtime_version (optional, string): The runtime version. - simulator (optional, boolean): Whether to get a simulator build. - wait_for_in_progress (optional, boolean): Whether to wait for a matching in-progress build. Default: false.

Fingerprint job outputs

The fingerprint job produces the following outputs that can be referenced in subsequent jobs: - android_fingerprint_hash (string): The fingerprint hash for Android. - ios_fingerprint_hash (string): The fingerprint hash for iOS.

Fingerprint job type for CNG workflows

The fingerprint job type calculates a fingerprint of your project and has the following syntax: ```yaml jobs: fingerprint: type: fingerprint environment: production | preview | development # optional, defaults to production env: # optional list of environment variables ENV_VAR_NAME: value hooks: after_checkout: step[] # optional before_install_node_modules: step[] # optional after_install_node_modules: step[] # optional ``` Note: This job type only supports CNG (Continuous Native Generation) workflows. If you commit your android or ios directories, the fingerprint job won't work.

Deploy job outputs

The deploy job produces the following outputs that can be referenced in subsequent jobs: - deploy_json (string): JSON object containing the deployment details (output of npx eas-cli deploy --json). - deploy_url (string): URL to the deployment. It uses production URL if this was a production deployment. Otherwise, it uses the first alias URL or the deployment URL. - deploy_alias_url (string): Alias URL to the deployment (for example, https://account-project--alias.expo.app). - deploy_deployment_url (string): Unique URL to the deployment (for example, https://account-project--uniqueid.expo.app). - deploy_identifier (string): Identifier of the deployment. - deploy_dashboard_url (string): URL to the deployment dashboard (for example, https://expo.dev/projects/[project]/hosting/deployments).

Deploy job type for EAS Hosting

The deploy job type has the following syntax: ```yaml jobs: deploy_web: type: deploy params: alias: string # optional prod: boolean # optional source_maps: boolean # optional hooks: after_checkout: step[] # optional before_install_node_modules: step[] # optional after_install_node_modules: step[] # optional ``` Parameters: - alias (optional, string): The alias to deploy to. - prod (optional, boolean): Whether to deploy to production. - source_maps (optional, boolean): Whether to upload source maps with the deployment.

Build job type syntax and parameters

The build job type has the following syntax: ```yaml jobs: build_app: type: build runs_on: string # optional params: platform: android | ios # required profile: string # optional - default: production message: string # optional refresh_ad_hoc_provisioning_profile: boolean # optional hooks: before_install_node_modules: step[] # optional after_install_node_modules: step[] # optional ``` Parameters: - platform (required, string): The platform to build for, either 'android' or 'ios'. - profile (optional, string): The build profile to use. Defaults to 'production'. - message (optional, string): Custom message attached to the build, corresponds to the --message flag when running eas build. - refresh_ad_hoc_provisioning_profile (optional, boolean): Refreshes the managed ad hoc provisioning profile before an iOS internal build starts, corresponds to the --refresh-ad-hoc-provisioning-profile flag when running eas build.

Doc job parameters

The doc job type accepts the following parameter: md (string, required) - Markdown content to display; supports ${{ ... }} workflow interpolation.

Give your agent this brain