Run this build on an iOS Simulator or Android Emulator straight from your pull request.
Description
Creates a shareable Device Preview link for an app artifact from this build. Opening the link boots a fresh iOS Simulator or Android Emulator in the browser, installs the app and launches it — nothing to download, and no local Xcode or Android SDK needed.
The link is exported as $BITRISE_DEVICE_PREVIEW_URL, so you can use it anywhere later in the Workflow:
post it to Slack, attach it to a GitHub check, drop it into release notes, or feed it to your own
notification tooling. Set post_pr_comment to true and the Step also posts it as a pull request
comment for you.
- iOS — a zipped simulator
.appbundle, for example the$BITRISE_APP_DIR_PATH.zipproduced by the Xcode build for simulator Step. A Simulator cannot run a device build, so.ipafiles are rejected. - Android — an
.apk. Android App Bundles (.aab) cannot be installed directly and are rejected.
If the file was already uploaded by an earlier Deploy to Bitrise.io Step, this Step reuses that artifact instead of uploading it again.
- The Step fails the build if it cannot create a link. Set
is_skippable: trueon the Step in your Workflow if you would rather a preview problem did not stop the build. - Links expire after 24 hours by default, and 72 hours is the maximum.
- Each open of a link starts its own session, which shuts down automatically once nobody is watching it.
Add this step directly to your workflow in the Bitrise Workflow Editor.
You can also run this step directly with Bitrise CLI.
Inputs
| Key | Description | Flags | Default |
|---|---|---|---|
app_path |
Path to the app to open on a device. It can be: - a zipped iOS simulator app bundle, for example $BITRISE_APP_DIR_PATH.zip from the Xcode build for simulator Step - an iOS simulator .app directory, which the Step zips for you - an Android .apk Device builds (.ipa) and Android App Bundles (.aab) cannot be installed on a Simulator or Emulator, so the Step rejects them. |
required | $BITRISE_APP_DIR_PATH.zip |
platform |
auto detects the platform from the app itself, which is what you usually want. Set it to ios or android to double-check the app you are passing in: the Step fails if the file turns out to be for the other platform. |
required | auto |
warm_pool_id |
ID of a Bitrise Remote Dev Environments warm pool to serve the link's opens from. Copy it from the pool's page in the RDE UI or from bitrise-cli rde warm-pool view. Each open claims one of the pool's pre-booted device sessions when one is available, so the click-to-app time is the app download rather than a VM boot; when none is available a session is created from the pool's configuration. The pool must be workspace-owned and its configuration must boot a device of the app's platform. The pool fixes the device and the machine, so device_model, os_version, stack, machine_type, system_image and the emulator inputs cannot be set with it — the Step fails before uploading anything if they are. Deleting the pool invalidates the links minted with it. A pool-backed link opens sessions built from the pool's template, so a reviewer's device runs whatever that template's setup scripts and inputs set up. Without a pool, a link opens a bare device with only the app installed. Warm pools are created in the Bitrise web UI or with bitrise-cli rde warm-pool create. |
||
device_model |
Device to boot, for example iPhone 15 on iOS or pixel_7 on Android. Empty uses the platform default. The value is not validated when the link is created, so a name that does not exist only surfaces when someone opens the link. |
||
os_version |
OS version to boot, for example 17.5. Empty uses the platform default. iOS only: on Android the OS version comes from the system image, so set system_image instead. The Step fails if it is set for an Android app. |
||
stack |
Bitrise stack the preview sessions run on, for example linux-docker-android-22.04. Empty uses the default for the platform, which is what you usually want. The value is validated when the link is created: a stack that does not exist, cannot be provisioned, or does not match the app's platform fails the Step with the backend's message. The available stacks can be listed via the Bitrise API using a Workspace API token (GET /v1/workspaces/{workspace}/stacks). There is deliberately no cluster input — the cluster is derived from the stack and machine type combination, the same way session creation derives it. |
||
machine_type |
Machine type the preview sessions run on, for example g2.linux.x-large. Empty uses the default for the platform. The value is validated when the link is created: a machine type that does not exist or is too small to run a preview device (an Android emulator needs at least 4 CPUs and 8 GB RAM) fails the Step with the backend's message. The available machine types can be listed via the Bitrise API using a Workspace API token (GET /v1/workspaces/{workspace}/machine-types). |
||
system_image |
Android only: the sdkmanager system image package the emulator boots, for example system-images;android-34;google_apis;x86_64. Empty uses the platform default. Only images pre-installed on the stack can boot — they are never downloaded when the device starts. Asking for an image the stack does not have falls back to the closest installed one, with a notice shown to the viewer. |
||
emulator_ram_mb |
Android only: RAM given to the emulator, in MB. Empty sizes it to the host machine (a quarter of the host's RAM, clamped), which is what you usually want. When set it must be at least 1024, and it is checked against the machine type the link's sessions run on when the link is created — asking for more RAM than the machine has fails the Step. | ||
emulator_cores |
Android only: CPU cores given to the emulator. Empty sizes it to the host machine (half of the host's cores, clamped), which is what you usually want. Checked against the machine type the link's sessions run on when the link is created — asking for more cores than the machine has fails the Step. | ||
emulator_cold_boot |
Android only: boot the emulator cold (-no-snapshot-load) on every open of the link, and never save a quickboot snapshot. Every open then exercises a full first boot, which is slower but closer to what a fresh device does. |
required | false |
link_ttl_hours |
Link lifetime in hours. Empty uses the default of 24 hours, and 72 hours is the maximum. Short lifetimes are the main protection against a leaked link being used, so prefer the shortest one that still fits how your team reviews. | ||
auto_terminate_minutes |
How long a device session spawned by the link stays up after its last viewer disconnects, in minutes. Empty uses the default of 60 minutes. When set it must be at least 10 minutes — a shorter window would shut sessions down before the device finishes booting — and at most the maximum session lifetime, which bounds a session's total runtime no matter what: auto-terminate can be tuned but never turned off. | ||
post_pr_comment |
Post the link as a comment on the pull request this build belongs to. Off by default, so adding the Step to a busy Workflow cannot start commenting on everyone's pull requests until you opt in. Ignored when the build is not a pull request build. The link is always exported as $BITRISE_DEVICE_PREVIEW_URL either way, so you can share it however you like. |
required | false |
permanent_download_url_map |
Used to find the app among the artifacts a previous Deploy to Bitrise.io Step already uploaded, so the same file is not uploaded twice. When the app is not found here, the Step uploads it itself. | $BITRISE_PERMANENT_DOWNLOAD_URL_MAP |
|
verbose |
Enable verbose logging. | required | false |
build_url |
Unique build URL of this build on Bitrise.io. Set automatically. | required | $BITRISE_BUILD_URL |
build_api_token |
The build's API token for this build on Bitrise.io. Set automatically. | required, sensitive | $BITRISE_BUILD_API_TOKEN |
Outputs
| Environment Variable | Description |
|---|---|
BITRISE_DEVICE_PREVIEW_URL |
The shareable link that opens this build on a device. |
BITRISE_DEVICE_PREVIEW_EXPIRES_AT |
When the Device Preview link stops working, as an RFC 3339 timestamp. |
We welcome pull requests and issues against this repository.
For pull requests, work on your changes in a forked repository and use the Bitrise CLI to run step tests locally.
Learn more about developing steps: