> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tester.army/llms.txt
> Use this file to discover all available pages before exploring further.

# App Uploads

> Build and upload an iOS Simulator or Android app build so TesterArmy can test it in the cloud.

Before you can automate mobile tests in CI, you need an iOS Simulator build or Android APK/APKS to test against.

<Prompt description="Build and upload a mobile app with TesterArmy CLI">
  You are working in a mobile app repository. Build a TesterArmy-compatible mobile artifact and upload
  it with the TesterArmy CLI.

  Before running commands:

  * Inspect the repository structure and identify whether this is an iOS, Android, Expo, or React Native project.
  * Do not upload an `.ipa`, `.aab`, or `.xapk`.
  * Use an iOS Simulator `.app` build for iOS, or an emulator-runnable `.apk` / `.apks` for Android.
  * Use Release configuration for both platforms. If a Release build is blocked, report the blocker instead of falling back to Debug or a development build.
  * Do not hard-code API keys or project IDs in committed files.
  * Check whether `TESTERARMY_API_KEY` and `TESTERARMY_PROJECT_ID` are already available in the environment.

  For iOS:

  1. Build a release iOS Simulator app using `-sdk iphonesimulator -destination 'generic/platform=iOS Simulator'`. Do not use the `iphoneos` SDK. If this is an Expo / React Native project, run `npx expo prebuild --platform ios` first when native files need to be generated.
  2. Prefer uploading the raw `.app` directory with the CLI. The CLI can zip it for you.
  3. If a zipped artifact is required, zip the `.app` bundle with the app bundle at the archive root.

  For Android:

  1. Build a signed release APK with `x86_64` or `arm64-v8a` support, or use an existing release `.apks` split APK archive with all required splits for either ABI. A universal APK is fine if it includes either ABI; apps without native libraries are ABI-independent. ARM64 apps run through native translation on our Android 15 emulators. For Expo / React Native builds targeting the emulator directly, use `-PreactNativeArchitectures=x86_64`; an existing `arm64-v8a` build does not need rebuilding solely for its architecture.
  2. If this is an Expo / React Native project, run `npx expo prebuild --platform android` first when native files need to be generated.
  3. Do not upload an Android App Bundle (`.aab`) or `.xapk`.

  Before uploading, verify the finished artifact's platform and architectures, its Android signature if applicable, and that it opens without Metro, Expo Go, or a development server. For iOS, check that `CFBundleSupportedPlatforms` contains `iPhoneSimulator` and that the executable and embedded frameworks target the Simulator.

  Upload the artifact:

  ```bash theme={"theme":"vesper"}
  mkdir -p .testerarmy

  testerarmy upload-app \
    --app-path <path-to-app-artifact> \
    --project "$TESTERARMY_PROJECT_ID" \
    --output .testerarmy/upload.json
  ```

  If this is a temporary CI upload, add `--remove-after 3600`.

  After uploading:

  * Print the uploaded app ID from `.testerarmy/upload.json`.
  * Tell the user which artifact path was uploaded.
  * Tell the user whether the artifact was iOS or Android based on the file type.
  * Do not run mobile tests unless the user explicitly asks you to.
</Prompt>

## What you need to upload

<Tabs>
  <Tab title="iOS">
    Upload an **iOS Simulator build** as `.app.zip` or `.zip` (archive a `.app` bundle at the zip root). The CLI can also accept a raw `.app` directory and zip it for you.

    <Warning>
      **Simulator builds only**

      Do not upload an `.ipa`. That is a device build. TesterArmy needs a `.app`
      bundle built for **iOS Simulator** with the `.app` directory at the archive root.
    </Warning>

    ### Build for iOS Simulator

    If you already have an Xcode project, build a simulator app with `xcodebuild`:

    ```bash theme={"theme":"vesper"}
    xcodebuild -workspace ios/MyApp.xcworkspace \
      -scheme MyApp \
      -configuration Release \
      -sdk iphonesimulator \
      -destination 'generic/platform=iOS Simulator' \
      -derivedDataPath ios/build \
      build
    ```

    The simulator app bundle usually ends up here:

    ```bash theme={"theme":"vesper"}
    ios/build/Build/Products/Release-iphonesimulator/MyApp.app
    ```

    If you are using Expo / React Native, the [mobile example app](https://github.com/tester-army/mobile-example) is a good reference. Its build flow looks like this:

    ```bash theme={"theme":"vesper"}
    npx expo prebuild --platform ios

    xcodebuild -workspace ios/testerarmy.xcworkspace \
      -scheme testerarmy \
      -configuration Release \
      -sdk iphonesimulator \
      -destination 'generic/platform=iOS Simulator' \
      -derivedDataPath ios/build \
      build
    ```

    ### Zip the `.app` bundle

    For dashboard uploads and the presigned API upload flow, archive the `.app` bundle after the build completes:

    ```bash theme={"theme":"vesper"}
    cd ios/build/Build/Products/Release-iphonesimulator
    zip -r MyApp.app.zip MyApp.app
    ```

    You should end up with a file like `MyApp.app.zip` whose top-level entry is `MyApp.app/`, not `Payload/MyApp.app/`.
  </Tab>

  <Tab title="Android">
    Upload an **Android build** as `.apk` / `.apks` when Android support is enabled for your workspace.

    <Warning>
      **Android formats**

      Android uploads must be a single `.apk` or a split APK archive (`.apks`).
      `.aab` and `.xapk` are not supported.
    </Warning>

    ### Build an Android APK/APKS

    Our Android 15 cloud emulators support `x86_64` and `arm64-v8a` apps. The emulator runs on `x86_64` and uses native translation for ARM64 libraries, so an ARM64-only APK can run too. Apps without native libraries work across architectures.

    Upload a signed Release APK that launches without a development server. Split APK archives (`.apks`) must also contain Release builds and all required splits for either `x86_64` or `arm64-v8a`. Run a test with your app to verify its native dependencies work on the emulator.

    Build the release variant using your project's signing configuration:

    ```bash theme={"theme":"vesper"}
    ./gradlew assembleRelease
    ```

    If you are using Expo / React Native, the [mobile example app](https://github.com/tester-army/mobile-example) is a good reference. Its Android build flow looks like this:

    ```bash theme={"theme":"vesper"}
    npx expo prebuild --platform android

    cd android
    ./gradlew assembleRelease -PreactNativeArchitectures=x86_64
    ```

    This example targets `x86_64` to avoid native translation. You can also use `-PreactNativeArchitectures=arm64-v8a` or upload an existing ARM64 build.

    The APK usually ends up under `android/app/build/outputs/apk/`. Verify that the final APK is signed and its packaged native libraries support `x86_64` or `arm64-v8a` before uploading it. Adapt the Gradle task to your app's module and flavor when needed.
  </Tab>
</Tabs>

## Upload via the dashboard

Go to your project and click the **Mobile** tab. Then click **Browse files** and select your `.app.zip`, `.apk`, or `.apks`.
TesterArmy uploads the artifact to temporary storage first, validates the bundle metadata, and then promotes the validated artifact into your project. If validation fails, the temporary upload is removed and no project app is created.

<img src="https://mintcdn.com/tester-army/cxPvc8T8okiKYoP3/images/uploading-mobile-app.png?fit=max&auto=format&n=cxPvc8T8okiKYoP3&q=85&s=cab82bec8d7a50f21dc0e60e16967b8f" alt="Upload app via dashboard" width="1425" height="539" data-path="images/uploading-mobile-app.png" />

## Upload via the API

For large artifacts, use the three-step presigned flow that streams the bytes straight to storage:

1. `POST /api/v1/projects/{projectId}/mobile/upload` with `{ filename, fileSize }`. The response includes an `uploadUrl` and `storageKey`.
2. `PUT` the archive bytes to `uploadUrl`.
3. `POST /api/v1/projects/{projectId}/mobile/upload/confirm` with the same `storageKey`, `filename`, and `fileSize`, plus optional `removeAfter`.

The presigned URL writes to temporary storage. The confirm step validates the artifact and promotes it into project storage; failed validation deletes the temporary object.

See the [API reference](/api-reference/projects/initiate-a-project-mobile-app-upload).

The direct multipart upload (`POST /api/v1/projects/{projectId}/mobile`) remains supported for existing integrations.

## Create your first mobile test

Before adding CI, upload your build, create at least one mobile test, and run it to make sure it passes. Runs target your most recent uploaded app for the platform automatically; pass an explicit app ID via the API or CLI only when you need to pin a specific build.

When writing prompts, guide the agent like you would guide a human user.

**Weak prompt example:** *"Open settings"*

**Strong prompt example:** *"Tap the profile icon in the top right, open Settings, and verify the notifications toggle is visible"*

Specific prompts produce more reliable tests and make CI failures easier to understand.

## Upload with the CLI

The TesterArmy CLI can upload a raw `.app` directory, an `.app.zip`, an `.apk`, or an `.apks`. Raw `.app` directories are packed for you with the app bundle at the archive root:

```bash theme={"theme":"vesper"}
testerarmy upload-app \
  --app-path ios/build/Build/Products/Release-iphonesimulator/MyApp.app \
  --project <projectId>
```

`--app-path` and `--project` are required.

For temporary CI uploads, you can set `removeAfter` in seconds:

```bash theme={"theme":"vesper"}
testerarmy upload-app \
  --app-path MyApp.apk \
  --project <projectId> \
  --remove-after 3600 \
  --json
```

Use `--output ./result.json` to write the JSON payload to a specific file, or
`--output ./artifacts/` to write `ta-app-upload-<date>.json` inside a directory.

The command rejects `.ipa` archives.
It also rejects Android `.aab` and `.xapk` bundles.

If you use Expo EAS, see [Expo EAS](/mobile/expo-eas) for the full workflow that
builds the mobile app artifact, downloads it, uploads it, and runs
TesterArmy tests.

## Notes

* Use `removeAfter` to auto-delete temporary uploads created during CI.
* Each project has a 2 GB storage limit.
* **Auto-delete Oldest App** is enabled by default: when a new upload would exceed the storage limit, TesterArmy automatically deletes the oldest uploaded app to make room. Apps used by queued or running tests are never auto-deleted. Disable the toggle in the project's Mobile tab to have over-limit uploads rejected instead.
* Our GitHub Action can upload the `.app` directory directly, so you do not need to zip it when running through GitHub Actions.
* Android uploads require workspace-level Android support to be enabled.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.