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. AddTESTERARMY_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.
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:
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 needenvman.
- iOS
- Android
bitrise.yml
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 Androidrelease variant requires signing, add sign-apk@1 after android-build@1 and upload $BITRISE_SIGNED_APK_PATH instead of $BITRISE_APK_PATH.
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.bitrise.yml
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.
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.