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.
Update job outputs
The update job produces the following outputs that can be referenced in subsequent jobs:
- first_update_group_id (string): The ID of the first update group.
- updates_json (string): A JSON string containing information about all update groups.
Update-rollout job type syntax and parameters
The update-rollout job type increases the rollout percentage of an in-progress EAS Update rollout. Its syntax is:
```yaml
jobs:
roll_out_update:
type: update-rollout
params:
update_group_id: string # required
rollout_percentage: number # optional - 0 to 100, defaults to 100
```
Parameters:
- update_group_id (required, string): The ID of the update group whose rollout to change. This is typically the first_update_group_id output of a preceding update job. The group must have an in-progress rollout.
- rollout_percentage (optional, number): Percentage of users this update group should be rolled out to. Must be an integer between 0 and 100, and no less than the group's current rollout percentage. Defaults to 100.
Update-rollout job outputs
The update-rollout job produces the following outputs that can be referenced in subsequent jobs:
- update_group_id (string): The ID of the update group that was rolled out.
- rollout_percentage (number): The rollout percentage that was applied to the update group.
- updates_json (string): A JSON string containing information about all updates in the group.
Branch-delete job type syntax and parameters
The branch-delete job type deletes an EAS Update branch. Its syntax is:
```yaml
jobs:
delete_branch:
type: branch-delete
params:
branch_name: string # required
fail_on_missing: boolean # optional, default: false
```
Parameters:
- branch_name (required, string): Name of the EAS Update branch to delete.
- fail_on_missing (optional, boolean): If false, the job succeeds when the branch does not exist. If true, the job fails with a validation error when the branch is missing. Defaults to false.
Branch-delete job outputs
The branch-delete job produces the following outputs that can be referenced in subsequent jobs:
- branch_id (string): UUID of the deleted branch, or null if the branch was missing and fail_on_missing is false.
- branch_name (string): The branch name from params.branch_name.
Maestro job type syntax
The maestro job type runs Maestro tests on an Android Emulator or iOS Simulator build. Its syntax is:
```yaml
jobs:
run_maestro_tests:
type: maestro
environment: production | preview | development # optional - defaults to preview
image: string # optional
runs_on: string # optional
params:
build_id: string # required
flow_path: string | string[] # required
shards: number # optional - defaults to 1
retries: number # optional - defaults to 0
retry_failed_only: boolean # optional - defaults to true
record_screen: boolean # optional - defaults to false
include_tags: string | string[] # optional
exclude_tags: string | string[] # optional
maestro_version: string # optional - defaults to latest
android_system_image_package: string # optional
device_identifier: string | { android?: string, ios?: string } # optional
output_format: string # optional - defaults to junit
skip_build_check: boolean # optional - defaults to false
hooks:
after_checkout: step[] # optional
before_maestro_tests: step[] # optional
after_maestro_tests: step[] # optional
```
Note: Maestro tests are in alpha status.
Build job prerequisite configuration
Before using the build job type, your project must be set up for EAS Build. Requirements:
1. eas.json must contain the build profile the job uses.
2. App signing credentials must be configured for the platform.
3. You can set up credentials without running a build first by running: eas credentials:configure-build -p <platform> -e <profile> with the same platform and profile the job uses.
Build job environment variables
If you need certain environment variables during the build process in a build job, include them in your eas.json for your specified build profile. They will be pulled from EAS environment variables.
Deploy job prerequisite configuration
Before using the deploy job type, your project must be set up for EAS Hosting. See the 'Get started with EAS Hosting' documentation for setup instructions.
Fingerprint job environment variable consistency
To ensure fingerprints match your builds when using the fingerprint job, use the same environment setting as your build profile. For environment variables, it is recommended to use EAS environment variables rather than the env field for better consistency.
Get-build job wait_for_in_progress behavior
When wait_for_in_progress is set to true in a get-build job, the job prioritizes continuing immediately with a successful build, but it also looks for in-progress builds. If no successful build is found, the job waits for an in-progress build to complete before continuing. If the matched build succeeds, the job returns the successful build. If the matched build fails, the job is marked as successful but its outputs will be empty—as if the build has not been matched.
Submit job CI/CD prerequisite configuration
Submission jobs require additional configuration to run within a CI/CD process. See the Google Play Store CI/CD submission guide and Apple App Store CI/CD submission guide for more information.
TestFlight job external distribution prerequisite
When distributing to external groups or submitting for Beta App Review (external_groups and/or submit_beta_review: true), the build must have the required TestFlight test information completed in App Store Connect before the job can succeed. See Apple's 'Provide test information' documentation.
TestFlight job App Store Connect integration prerequisite
When using the asc_build_id parameter (submitting an already uploaded build), configure your App Store Connect connection in Project settings > General > Connections. The build must already exist in App Store Connect and be ready for submission.
Update job prerequisite configuration
Before using the update job type, EAS Update must be configured. Run npx eas-cli@latest update:configure, then create new builds. Learn more about configuring EAS Update.
Update job branch vs channel parameters
In the update job, provide either a branch or a channel parameter, not both. If branch is not provided, the branch from the workflow run will be used. For manually run workflows, you must provide a value.
Build job hooks
The build job supports the following hooks:
- before_install_node_modules: steps to run before the build installs your project's dependencies.
- after_install_node_modules: steps to run after the build installs your project's dependencies.
Deploy job hooks
The deploy job supports the following hooks:
- after_checkout: steps to run after the job checks out your project.
- before_install_node_modules: steps to run before the job installs your project's dependencies.
- after_install_node_modules: steps to run after the job installs your project's dependencies.
Fingerprint job hooks
The fingerprint job supports the following hooks:
- after_checkout: steps to run after the job checks out your project.
- before_install_node_modules: steps to run before the job installs your project's dependencies.
- after_install_node_modules: steps to run after the job installs your project's dependencies.
Submit job hooks
The submit job supports the following hooks:
- after_checkout: steps to run after the job checks out your project.
- before_install_node_modules: steps to run before the job installs your project's dependencies.
- after_install_node_modules: steps to run after the job installs your project's dependencies.
- before_submit: steps to run before the submission starts.
- after_submit: steps to run after the submission completes.
TestFlight job hooks for build_id variant
The TestFlight job (with build_id) supports the following hooks:
- after_checkout: steps to run after the job checks out your project.
- before_install_node_modules: steps to run before the job installs your project's dependencies.
- after_install_node_modules: steps to run after the job installs your project's dependencies.
Hooks are not supported when submitting an already uploaded build (asc_build_id variant) because that job variant does not run on a worker.
Update job hooks
The update job supports the following hooks:
- after_checkout: steps to run after the job checks out your project.
- before_install_node_modules: steps to run before the job installs your project's dependencies.
- after_install_node_modules: steps to run after the job installs your project's dependencies.
- before_update: steps to run before publishing the update.
- after_update: steps to run after publishing the update. Hook steps can access files produced during publishing (for example, sourcemaps in the dist directory).
Build job example - basic iOS build
This workflow builds your iOS app whenever you push to the main branch:
```yaml
name: Build iOS app
on:
push:
branches: ['main']
jobs:
build_ios:
name: Build iOS
type: build
params:
platform: ios
profile: production
```
Build job example - parallel builds for all platforms
This workflow builds both Android and iOS apps in parallel when you push to the main branch:
```yaml
name: Build for all platforms
on:
push:
branches: ['main']
jobs:
build_android:
name: Build Android
type: build
params:
platform: android
profile: production
build_ios:
name: Build iOS
type: build
params:
platform: ios
profile: production
```
Build job example - with environment variables
This workflow builds your Android app with custom environment variables:
```yaml
name: Build with environment variables
on:
push:
branches: ['main']
jobs:
build_android:
name: Build Android
type: build
env:
APP_ENV: production
API_URL: https://api.example.com
params:
platform: android
profile: production
```
Build job example - with different profiles
This workflow creates two different Android builds using different profiles:
```yaml
name: Build with different profiles
on:
push:
branches: ['main']
jobs:
build_android_development:
name: Build Android Development
type: build
params:
platform: android
profile: development
build_android_production:
name: Build Android Production
type: build
params:
platform: android
profile: production
```
Build job example - iOS internal build with refreshed ad hoc profile
This workflow builds your iOS app for internal distribution and refreshes the ad hoc provisioning profile:
```yaml
name: Build iOS internal
on:
push:
branches: ['main']
jobs:
build_ios:
name: Build iOS Internal
type: build
params:
platform: ios
profile: preview
refresh_ad_hoc_provisioning_profile: true
```
Deploy job example - basic production deployment
This workflow deploys your application to production using EAS Hosting:
```yaml
name: Basic Deployment
jobs:
deploy:
name: Deploy to Production
type: deploy
params:
prod: true
```
Deploy job example - branch-based deployment
This workflow deploys your application to production when you merge to the main branch, and makes a non-production deployment on all other branches:
```yaml
name: Deploy
on:
push:
branches: ['*']
jobs:
deploy:
name: Deploy
type: deploy
params:
prod: ${{ github.ref_name == 'main' }}
```
Deploy job example - with custom alias
This workflow deploys your application to a custom alias in production:
```yaml
name: Deployment with Alias
jobs:
deploy:
name: Deploy with Alias
type: deploy
params:
alias: my-custom-alias
prod: true
```
Fingerprint job example - basic fingerprint calculation
This workflow calculates fingerprints for both Android and iOS builds. The environment should match your build profile for accurate fingerprint matching:
```yaml
name: Basic Fingerprint
jobs:
fingerprint:
name: Calculate Fingerprint
type: fingerprint
environment: production
```
Fingerprint job example - with inline environment variables
This workflow calculates a fingerprint with inline environment variables:
```yaml
name: Fingerprint with Environment Variables
jobs:
fingerprint:
name: Calculate Fingerprint
type: fingerprint
environment: production
env:
APP_VARIANT: staging
API_URL: https://api.staging.example.com
```
Note: If you depend on inline environment variables, you will need to always make sure to set the right set of environment variables to the right values in every place (build profile, fingerprint job, update job, and so on) for fingerprints to match. It is recommended to use EAS Environment Variables instead.
Get-build job example - latest production build
This workflow retrieves the latest production build for iOS from the store distribution channel:
```yaml
name: Get Production Build
jobs:
get_build:
name: Get Latest Production Build
type: get-build
params:
platform: ios
profile: production
distribution: store
channel: production
```
Get-build job example - get build by version
This workflow retrieves a specific version of an Android build by its app version and build version:
```yaml
name: Get Build by Version
jobs:
get_build:
name: Get Specific Version Build
type: get-build
params:
platform: android
app_identifier: com.example.app
app_version: 1.0.0
app_build_version: 42
```
Get-build job example - simulator build with wait
This workflow retrieves a simulator build for iOS development. wait_for_in_progress is set to true so that if a build matching the filter already exists, the job will wait for it to complete before continuing:
```yaml
name: Get Simulator Build
jobs:
get_build:
name: Get Simulator Build
type: get-build
params:
platform: ios
simulator: true
profile: development
wait_for_in_progress: true
```
Submit job example - submit iOS build to App Store
This workflow submits an iOS build to the App Store using the production submit profile:
```yaml
name: Submit iOS Build
jobs:
build_ios:
name: Build iOS
type: build
params:
platform: ios
profile: production
submit:
name: Submit to App Store
type: submit
needs: [build_ios]
params:
build_id: ${{ needs.build_ios.outputs.build_id }}
profile: production
```
Submit job example - submit Android build to Play Store
This workflow submits an Android build to the Play Store using the production submit profile:
```yaml
name: Submit Android Build
jobs:
build_android:
name: Build Android
type: build
params:
platform: android
profile: production
submit:
name: Submit to Play Store
type: submit
needs: [build_android]
params:
build_id: ${{ needs.build_android.outputs.build_id }}
profile: production
```
TestFlight job example - full distribution with groups and changelog
This workflow distributes to both internal and external TestFlight groups with a changelog:
```yaml
name: TestFlight Distribution
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
```
TestFlight job example - upload with changelog only
This workflow uploads a build with a changelog but without specifying any groups to explicitly add the build to. The build will only get added to internal groups with "auto-distribute" enabled:
```yaml
name: TestFlight with Changelog
jobs:
testflight:
name: Upload with Changelog
type: testflight
params:
build_id: ${{ needs.build_ios.outputs.build_id }}
changelog: "${{ github.commit_message || 'Bug fixes' }}"
```
TestFlight job example - auto-distribute to TestFlight after App Store Connect upload
When a build is uploaded to App Store Connect, this workflow automatically adds the build to TestFlight groups, sets "What to Test" notes, and submits for Beta App Review:
```yaml
name: Distribute to TestFlight after ASC upload
on:
app_store_connect:
build_upload:
states:
- complete
jobs:
distribute_to_testflight:
name: Distribute to TestFlight
type: testflight
params:
asc_build_id: ${{ app_store_connect.build_upload.build.id }}
internal_groups:
- QA Team
external_groups:
- Public Beta
changelog: Build from CI
submit_beta_review: true
```
TestFlight job example - update changelog without re-submitting
For a build that already exists in App Store Connect, you can update the "What to Test" notes or group membership without triggering Beta App Review by setting submit_beta_review to false:
```yaml
name: Update TestFlight changelog
on:
workflow_dispatch:
inputs:
asc_build_id:
type: string
required: true
description: The App Store Connect build ID to update.
changelog:
type: string
required: true
description: The new "What to Test" notes.
jobs:
update_changelog:
name: Update changelog
type: testflight
params:
asc_build_id: ${{ inputs.asc_build_id }}
changelog: ${{ inputs.changelog }}
submit_beta_review: false
```
Update job example - basic production channel update
This workflow publishes an update to the production channel whenever you push to the main branch, using the commit message as the update message:
```yaml
name: Update Production
on:
push:
branches: ['main']
jobs:
update_production:
name: Update Production Channel
type: update
params:
channel: production
```
Update job example - platform-specific updates
This workflow publishes separate updates for Android and iOS platforms, allowing for platform-specific changes:
```yaml
name: Platform-specific Updates
on:
push:
branches: ['main']
jobs:
update_android:
name: Update Android
type: update
params:
platform: android
channel: production
update_ios:
name: Update iOS
type: update
params:
platform: ios
channel: production
```
Update job example - branch-based deployment
This workflow publishes updates based on the branch name, allowing for different environments (staging/production) based on the branch:
```yaml
name: Branch-based Updates
on:
push:
branches: ['main', 'staging']
jobs:
update_branch:
name: Update Branch
type: update
params:
branch: ${{ github.ref_name }}
message: 'Update for branch: ${{ github.ref_name }}'
```
Update job example - with sourcemaps upload to PostHog
This workflow publishes an update and then uploads the generated sourcemaps to PostHog using the built-in eas/posthog_upload_sourcemaps function:
```yaml
name: Update with sourcemaps
on:
push:
branches: ['main']
jobs:
update:
name: Publish update
type: update
params:
channel: production
hooks:
after_update:
- uses: eas/posthog_upload_sourcemaps
```
Update-rollout job example - staged rollout with approval
This workflow publishes an update to 25% of users, waits for approval, and only then completes the rollout to 100%:
```yaml
name: Update with staged rollout
on:
push:
branches: ['main']
jobs:
publish_update:
name: Publish update to 25% of users
type: update
params:
channel: production
rollout_percentage: 25
require_approval:
name: Roll out to all users?
type: require-approval
needs: [publish_update]
complete_rollout:
name: Roll out to all users
type: update-rollout
needs: [publish_update, require_approval]
params:
update_group_id: ${{ needs.publish_update.outputs.first_update_group_id }}
rollout_percentage: 100
```
Maestro job hooks
The Maestro job type supports the following hooks: after_checkout (steps to run after the job checks out your project), before_maestro_tests (steps to run before the tests start), after_maestro_tests (steps to run after the tests complete). These follow the general hooks syntax documented in jobs.<job_id>.hooks.
Maestro Cloud job parameters table
The maestro-cloud job type accepts the following parameters: build_id (string, required, example: ${{ needs.build_android.outputs.build_id }}) - ID of the build to test; maestro_project_id (string, required, example: proj_01jw6hxgmdffrbye9fqn0pyzm0) - ID of Maestro Cloud project; flows (string, required) - path to Maestro flow file or directory; maestro_api_key (string, optional, defaults to $MAESTRO_CLOUD_API_KEY) - API key for Maestro project; include_tags (string, optional, example: pull,push) - tags to include in tests (passed as --include-tags); exclude_tags (string, optional, example: disabled) - tags to exclude from tests (passed as --exclude-tags); maestro_version (string, optional, example: 1.30.0) - version of Maestro to use; maestro_config (string, optional, example: .maestro/config.yaml) - path to Maestro config.yaml (passed as --config); device_locale (string, optional, example: pl_PL) - device locale for tests (passed as --device-locale); device_model (string, optional, example: iPhone-11) - device model for tests (passed as --device-model); device_os (string, optional, example: iOS-18-2) - device OS for tests (passed as --device-os); skip_build_check (boolean, optional, default false) - skip validation of build; name (string, optional) - name for Maestro Cloud upload (passed as --name); branch (string, optional) - override for branch origin (passed as --branch); async (boolean, optional) - run tests asynchronously (passed as --async).
Maestro Cloud job outputs
The maestro-cloud job type provides the following outputs that can be referenced in subsequent jobs: maestro_cloud_url (string) - URL to Maestro Cloud upload results page; total_flows_count (number) - total number of flows executed; successful_flows_count (number) - number of flows that completed successfully (status SUCCESS or WARNING); failed_flows_count (number) - number of flows that failed (status ERROR or STOPPED); successful_flow_names_json (string) - JSON array containing names of successful flows; failed_flow_names_json (string) - JSON array containing names of failed flows. Note: When using async: true mode, only maestro_cloud_url output is guaranteed to be valid; other outputs may be invalid or empty.
Maestro Cloud hooks
The maestro-cloud job type supports the following hooks: after_checkout (steps to run after the job checks out your project), before_maestro_cloud (steps to run before the Maestro Cloud upload), after_maestro_cloud (steps to run after the Maestro Cloud upload). These follow the general hooks syntax documented in jobs.<job_id>.hooks.
Slack job parameters table
The slack job type accepts the following parameters: webhook_url (string, required) - Slack webhook URL to send the message to (use environment variable with ${{ env.SLACK_WEBHOOK_URL }}); message (string, required if payload is not provided) - message to send; payload (object, required if message is not provided) - Slack Block Kit payload to send.
GitHub Comment job parameters - auto mode
The github-comment job type in auto-with-overrides mode accepts the following parameters: message (string, optional, defaults to 'Your builds, updates, and deployments are ready for testing!') - custom message to include at top of comment; build_ids (string[], optional) - specific build IDs to include; if not specified, auto-discovers all completed/failed/canceled builds; use empty array [] to exclude builds; update_group_ids (string[], optional) - specific update group IDs to include; if not specified, auto-discovers all successful updates; use empty array [] to exclude updates; deployment_ids (string[], optional) - specific deployment IDs to include; if not specified, auto-discovers all successful deployments; use empty array [] to exclude deployments. Auto-discovery behavior: when build_ids, update_group_ids, or deployment_ids are undefined, the job automatically discovers all relevant content from current workflow; to explicitly exclude, pass empty array [].
GitHub Comment job parameters - payload mode
The github-comment job type in payload mode accepts the following parameter: payload (string, required) - raw markdown or HTML content to post as the comment; supports workflow variable interpolation. When using payload mode, you cannot specify any other parameters (message, build_ids, update_group_ids, deployment_ids).
GitHub Comment job outputs
The github-comment job type provides the following output: comment_url (string) - URL of the posted GitHub comment (only available when the comment is successfully posted).
Apple device registration request job parameters
The apple-device-registration-request job type accepts the following parameter: apple_team_identifier (string, optional) - Apple Team ID (example: ABCDE12345); if omitted and Expo account has exactly one Apple team, that team is used; must be set when account has no Apple teams or has two or more teams; when provided, EAS resolves or creates the team from the identifier.
Apple device registration request job outputs
After a team member approves the enrolled device, the apple-device-registration-request job provides the following outputs: apple_device_id (string) - Expo internal device ID; identifier (string) - device UDID; name (string) - device name (may be empty); model (string) - hardware model string (example: iPhone11,2, may be empty); device_class (string) - device class: iphone, ipad, or mac (may be empty); software_version (string) - iOS version string (may be empty). If a team member rejects the enrollment, the job fails and does not set outputs.
Require Approval job
The require-approval job type pauses workflow execution and requires approval from a user before continuing. The user can approve or reject, which translates to success or failure of the job. This job does not take any parameters.
Repack job parameters table
The repack job type accepts the following parameters: build_id (string, required) - source build ID to repack; profile (string, optional) - build profile to use, defaults to profile of source build retrieved from build_id; embed_bundle_assets (boolean, optional) - whether to embed bundle assets in repacked build, automatically determined by default; js_bundle_only (boolean, optional, default false) - whether to only repack JavaScript bundle (false means entire app metadata is updated); message (string, optional) - custom message attached to the build (corresponds to --message flag); repack_version (string, optional) - version of @expo/repack-app to use, defaults to latest; repack_package (string, optional, defaults to @expo/repack-app) - repack npm package to use; ios_signing_use_source_app_entitlements (boolean, optional, default false) - whether to use fastlane resign use_app_entitlements behavior to extract entitlements from app bundle and combine with new provisioning profile entitlements; ios_signing_app_entitlements_path (string, optional) - path to entitlements file (example: myApp/MyApp.entitlements); exclusive with ios_signing_use_source_app_entitlements.
Repack job hooks
The repack job type supports the following hooks: after_checkout (steps to run after the job checks out your project), before_install_node_modules (steps to run before the job installs dependencies), after_install_node_modules (steps to run after the job installs dependencies). These follow the general hooks syntax documented in jobs.<job_id>.hooks.