Bitrise
Bitrise can build your mobile app and then hand the artifact to TesterArmy to run a saved test group. Bitrise owns the build; TesterArmy owns the cloud simulator/emulator, app installation, test execution, and run orchestration, so you do not need to manage devices or emulators in your Bitrise Workflow.
There is no dedicated TesterArmy Bitrise Step. You drive the flow from a Script Step with the TesterArmy CLI, which keeps the integration a plain two-command sequence:
upload-appuploads the build and returns an app ID.cistarts the group, waits for every run to finish, and exits non-zero when something failed.
Prerequisites
Before you add the Workflow, make sure you have already:
- created a mobile project in TesterArmy,
- created at least one mobile test and run it manually so you know it passes,
- added that test to a test group,
- confirmed your Bitrise build produces a supported artifact (see Artifact requirements).
Add the secrets
TesterArmy needs three values. Add TESTERARMY_API_KEY on the Secrets tab of the Workflow Editor so it is masked and not exposed to pull requests from forks. The project and group IDs are not sensitive, so you can keep them in app.envs in bitrise.yml.
Do not tick Expose for Pull Requests on TESTERARMY_API_KEY unless you only build pull
requests from branches in your own repository. Bitrise exposes protected secrets to fork builds
when that option is enabled.
The CLI reads TESTERARMY_API_KEY from the environment automatically. The project, group, and app IDs have no environment-variable fallback, so they must be passed as flags.
Artifact requirements
TesterArmy runs your app on a cloud simulator or emulator, which constrains what Bitrise needs to produce:
An .ipa will not work. xcode-archive produces a device build; you need
xcode-build-for-simulator. On Android, an .aab will not work either — set build_type: apk.
The CLI accepts the raw .app directory and zips it for you, so you can pass $BITRISE_APP_DIR_PATH directly.
Run a group after the build
The simplest setup is one Workflow that builds, uploads, and runs the group. Because both CLI commands run in the same Script Step, the app ID stays a local shell variable and you do not need envman.
iOS
Android
The tools: nodejs entry makes Node available in $PATH before the first Step, which is what
npx needs. If your repository already pins Node through a .nvmrc, .node-version, or
.tool-versions file, you can use the Dependency installer Step instead.
Signing an Android release build
If your Android release variant requires signing, add sign-apk@1 after android-build@1 and upload $BITRISE_SIGNED_APK_PATH instead of $BITRISE_APK_PATH. TesterArmy also accepts a debug APK, so building variant: debug is a valid way to avoid signing config in the test Workflow.
Prefer release builds when the app runs without a Metro dev server. See Dev Builds and Metro for the React Native caveats.
Build once, test both platforms
To test iOS and Android from a single trigger, split the work into a Bitrise Pipeline. The build Workflows run on the stack they need, share the artifact as a Pipeline intermediate file, and the test Workflows run on cheaper Linux machines because the CLI only needs Node.
deploy-to-bitrise-io shares each artifact under an env-var key, and pull-intermediate-files restores that same env var in the downstream Workflow, so the upload command is identical to the single-Workflow version. Directories such as the iOS .app bundle are archived and re-extracted for you.
If you split upload and test across two Workflows instead, pass the app ID between Steps with
envman add --key TESTERARMY_APP_ID --value "$APP_ID". Do not use --delete-app-after-run in
that case unless the deleting Workflow is the last consumer of the app — rely on --remove-after
instead.
Command reference
upload-app
The written JSON contains app and uploadedAppId:
ci
ci always polls until every run reaches a terminal state or the timeout elapses; there is no separate wait flag.
Exit codes
Bitrise fails the Step, and therefore the build, on any non-zero exit code.
Reporting results back to your Git provider
TesterArmy reports through GitHub, not through Bitrise. Passing --commit-sha and --pr-number only produces a GitHub check and PR comment when the TesterArmy project is connected to the GitHub repository containing that commit — configure it on the project’s Integrations tab. See Connect GitHub.
For repositories hosted on GitLab or Bitbucket, the Bitrise build status is the gate and full evidence lives in the TesterArmy dashboard. TesterArmy does not post GitLab merge request or Bitbucket pull request statuses.
Keeping storage under control
Each project has a 2 GB storage limit, and CI uploads accumulate quickly. Use both mechanisms together:
--remove-after 3600onupload-appis the safety net. TesterArmy removes the upload even if the build is aborted or the Step never reaches cleanup.--delete-app-after-runoncideletes the app as soon as the runs finish. It is skipped when the run timed out or the runs are not terminal, so the app stays available for debugging.
See App Uploads for the storage limits and auto-delete behavior.
Troubleshooting
Missing API key. Run testerarmy auth first or set TESTERARMY_API_KEY.
The Step exits with code 2. The secret is either not defined or not exposed to this Workflow. Check the Secrets tab, and remember that secrets are not available to builds triggered by pull requests from forks unless you explicitly expose them.
npx: command not found
Node is not on $PATH. Add the tools: nodejs entry shown above, or add a dependency-installer@1 Step before the Script Step.
The upload is rejected as an unsupported format
You are passing an .ipa, .aab, or .xapk. Switch the iOS build to xcode-build-for-simulator, or set build_type: apk on android-build.
$BITRISE_APP_DIR_PATH is empty
The Script Step runs before the build Step, or the build Step failed without failing the build. Confirm xcode-build-for-simulator appears earlier in the Workflow. In a Pipeline, confirm pull-intermediate-files lists the correct artifact_sources and that the build Workflow shared the path with deploy-to-bitrise-io.
The build passes but no tests ran
--group points at a group with no mobile tests in it. Groups containing only web tests produce an empty run set.
The Step fails with --delete-app-after-run but the tests passed
--delete-app-after-run requires both --app-id and --project. If the delete request itself fails, the CLI rethrows and exits 2 even though the runs passed. Drop the flag and rely on --remove-after if your API key lacks delete permission.
