Run TesterArmy mobile tests from Expo EAS workflows by uploading an EAS iOS Simulator build or Android APK and triggering a remote test group.
Before you set it up, make sure you have already:
Also make sure that you have configured Expo EAS with Github
These values can be found in the TesterArmy Dashboard:
Set TESTERARMY_API_KEY as an EAS secret or sensitive environment variable. Do not commit it, and
do not expose it through an EXPO_PUBLIC_* environment variable.
Below you will find instructions for AI agent to set up EAS integration with TesterArmy for you.
You are working in an Expo app repository. Add TesterArmy mobile testing through Expo EAS workflows.
Before editing files:
* Inspect the existing `eas.json`, `.eas/workflows`, `package.json`, and package manager lockfile.
* Do not overwrite an existing EAS workflow. Create a new workflow file or make the smallest safe edit.
* Do not hard-code secrets, API keys, project IDs, or group IDs in committed files.
* Use the repository’s existing package manager style when adding commands.
Implement this setup:
1. Detect which platforms are already configured in the app (`ios`, `android`, or both). If it is not clear, ask the user whether to set up iOS, Android, or both before editing workflow files.
2. For iOS, ensure `eas.json` has a TesterArmy iOS Simulator build profile. Prefer `testerarmy-ios-simulator`. If the project already has a compatible simulator profile, reuse it and keep the workflow profile name in sync.
3. For Android, ensure `eas.json` has a TesterArmy APK build profile. Prefer `testerarmy-android-apk`. If the project already has a compatible APK profile, reuse it and keep the workflow profile name in sync.
4. The iOS profile must set `ios.simulator` to `true`. TesterArmy needs a `.app` simulator build, not an `.ipa` device build.
5. The Android profile must produce an APK. Prefer `android.buildType: "apk"`. TesterArmy needs a `.apk`; `.aab` and `.xapk` are not supported.
6. Create `.eas/workflows/testerarmy-mobile-tests.yml` if it does not already exist.
7. The workflow should support `push` to `main`, `pull_request` to `main`, and `workflow_dispatch`.
8. The workflow should read these values from EAS environment variables:
* `TESTERARMY_API_KEY`
* `TESTERARMY_PROJECT_ID`
* `TESTERARMY_GROUP_ID`
9. The workflow should build only the selected platform artifacts: an iOS Simulator app, an Android APK, or both.
10. The workflow should download the selected build artifacts with `eas/download_build`.
11. The workflow should upload each downloaded artifact with `npx --yes testerarmy@latest upload-app`.
12. The workflow should run the saved TesterArmy group for each selected platform, using `--platform ios` for iOS and `--platform android` for Android, plus the uploaded app ID for that platform.
13. The workflow should pass commit SHA for GitHub check reporting when the EAS/GitHub context provides it.
14. The workflow should pass PR number only when the workflow is running for a pull request.
15. The workflow should delete each uploaded app after its run.
Use this workflow as the baseline and adapt it to the repository if needed:
```yaml
name: TesterArmy Mobile Tests
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch: {}
jobs:
build_ios:
name: Build iOS Simulator app
type: build
environment: preview
params:
platform: ios
profile: testerarmy-ios-simulator
build_android:
name: Build Android app
type: build
environment: preview
params:
platform: android
profile: testerarmy-android-apk
upload_ios_app:
name: Upload iOS app to TesterArmy
needs: [build_ios]
environment: preview
outputs:
app_id: ${{ fromJSON(steps.upload_app.outputs.upload_result).uploadedAppId }}
steps:
- uses: eas/checkout
- uses: eas/download_build
id: download_build
with:
build_id: ${{ needs.build_ios.outputs.build_id }}
extensions:
- app
- name: Upload app
id: upload_app
run: |
set -euo pipefail
APP_PATH="${{ steps.download_build.outputs.artifact_path }}"
mkdir -p .testerarmy
npx --yes testerarmy@latest upload-app \
--app-path "$APP_PATH" \
--project "$TESTERARMY_PROJECT_ID" \
--output .testerarmy/upload.json
set-output upload_result "$(tr -d '\n' < .testerarmy/upload.json)"
upload_android_app:
name: Upload Android app to TesterArmy
needs: [build_android]
environment: preview
outputs:
app_id: ${{ fromJSON(steps.upload_app.outputs.upload_result).uploadedAppId }}
steps:
- uses: eas/checkout
- uses: eas/download_build
id: download_build
with:
build_id: ${{ needs.build_android.outputs.build_id }}
extensions:
- apk
- name: Upload app
id: upload_app
run: |
set -euo pipefail
APP_PATH="${{ steps.download_build.outputs.artifact_path }}"
mkdir -p .testerarmy
npx --yes testerarmy@latest upload-app \
--app-path "$APP_PATH" \
--project "$TESTERARMY_PROJECT_ID" \
--output .testerarmy/upload.json
set-output upload_result "$(tr -d '\n' < .testerarmy/upload.json)"
run_ios_tests:
name: Run iOS TesterArmy tests
needs: [upload_ios_app]
environment: preview
steps:
- uses: eas/checkout
- name: Run tests
run: |
set -euo pipefail
APP_ID="${{ needs.upload_ios_app.outputs.app_id }}"
COMMIT_SHA="${{ github.sha }}"
EVENT_NAME="${{ github.event_name }}"
PR_NUMBER="${{ github.event.pull_request.number || '' }}"
TIMEOUT_MS="1800000"
POLL_INTERVAL_SECONDS="10"
mkdir -p .testerarmy
args=(
ci
--group "$TESTERARMY_GROUP_ID"
--project "$TESTERARMY_PROJECT_ID"
--platform ios
--app-id "$APP_ID"
--commit-sha "$COMMIT_SHA"
--timeout "$TIMEOUT_MS"
--poll-interval-seconds "$POLL_INTERVAL_SECONDS"
--output .testerarmy/ci-result.json
--delete-app-after-run
)
if [ "$EVENT_NAME" = "pull_request" ] && [ -n "$PR_NUMBER" ]; then
args+=(--pr-number "$PR_NUMBER")
fi
npx --yes testerarmy@latest "${args[@]}"
run_android_tests:
name: Run Android TesterArmy tests
needs: [upload_android_app]
environment: preview
steps:
- uses: eas/checkout
- name: Run tests
run: |
set -euo pipefail
APP_ID="${{ needs.upload_android_app.outputs.app_id }}"
COMMIT_SHA="${{ github.sha }}"
EVENT_NAME="${{ github.event_name }}"
PR_NUMBER="${{ github.event.pull_request.number || '' }}"
TIMEOUT_MS="1800000"
POLL_INTERVAL_SECONDS="10"
mkdir -p .testerarmy
args=(
ci
--group "$TESTERARMY_GROUP_ID"
--project "$TESTERARMY_PROJECT_ID"
--platform android
--app-id "$APP_ID"
--commit-sha "$COMMIT_SHA"
--timeout "$TIMEOUT_MS"
--poll-interval-seconds "$POLL_INTERVAL_SECONDS"
--output .testerarmy/ci-result.json
--delete-app-after-run
)
if [ "$EVENT_NAME" = "pull_request" ] && [ -n "$PR_NUMBER" ]; then
args+=(--pr-number "$PR_NUMBER")
fi
npx --yes testerarmy@latest "${args[@]}"
```
Use these command shapes:
```bash
npx --yes testerarmy@latest upload-app \
--app-path "$APP_PATH" \
--project "$PROJECT_ID" \
--output .testerarmy/upload.json
```
```bash
npx --yes testerarmy@latest ci \
--group "$GROUP_ID" \
--project "$PROJECT_ID" \
--platform ios \
--app-id "$APP_ID" \
--commit-sha "$COMMIT_SHA" \
--timeout "$TIMEOUT_MS" \
--poll-interval-seconds "$POLL_INTERVAL_SECONDS" \
--output .testerarmy/ci-result.json
```
Use `--platform android` for Android test runs.
If a PR number is available, append:
```bash
--pr-number "$PR_NUMBER"
```
If cleanup is enabled, append:
```bash
--delete-app-after-run
```
After editing:
* Show the user which files changed.
* Tell the user to configure `TESTERARMY_API_KEY`, `TESTERARMY_PROJECT_ID`, and `TESTERARMY_GROUP_ID` in their EAS environment.
* Tell the user which EAS workflow command to run.
* Do not run the real TesterArmy CLI or EAS build unless the user explicitly asks you to.
Finish by summarizing the files changed and the manual test command.TesterArmy requires an iOS Simulator build profile and an Android APK build profile in EAS. Add the following snippet to your eas.json file:
For Android builds, make sure your Expo config has an Android package name, for example
android.package in app.json.
Here is an example workflow file that:
When your workflow is triggered by a pull request, TesterArmy will create a GitHub check and comment on the PR.
When workflow is triggered by a commit (eg. on push to main), TesterArmy will create a GitHub check on the commit.
To enable this, you need to configure your TesterArmy project with your GitHub repository. You can do it in Integrations Tab in project.
You can find a working example repository here.
TesterArmy requires an iOS Simulator .app build or Android .apk build. If you are using an iOS physical-device build, build a simulator app first. If you are using Android, make sure the EAS profile produces an APK, not an .aab.
Prefer release builds for CI, especially for Android runs that execute without a Metro dev server.
If you are seeing this error, it means that your TesterArmy project has no GitHub integration configured. You can configure it in Integrations Tab in project.