How to Integrate Maestro with CI/CD Pipelines: Complete Technical Guide
Maestro automatically detects CI environments via environment variables and disables interactive prompts, enabling headless test execution with the MAESTRO_CLI_NO_ANALYTICS=true setting and --flatten-debug-output flag for deterministic artifact collection.
Maestro is a command-line UI testing framework for mobile applications designed to run seamlessly in automated build pipelines. According to the mobile-dev-inc/Maestro source code, the CLI includes built-in CI detection logic that suppresses UI-only features and adapts output for machine consumption, making it straightforward to integrate Maestro with CI/CD pipelines across GitHub Actions, CircleCI, GitLab CI, Jenkins, and custom runners.
CI Environment Detection in Maestro
Maestro identifies CI environments automatically through the CiUtils class located in maestro-cli/src/main/java/maestro/cli/util/CiUtils.kt. The CiUtils.getCiProvider() function (lines 5-19) scans for known CI provider environment variables:
GITHUB_ACTIONSCIRCLECITEAMCITY_VERSIONGITLAB_CIJENKINS_HOME
When detected, Maestro disables progress bars, suppresses interactive prompts, and routes output appropriately for headless execution.
Overriding CI Detection for Custom Runners
If your CI provider is not in the built-in list, force detection by setting the MDEV_CI environment variable:
export MDEV_CI=your-ci-name
As implemented in CiUtils.kt, this override returns your custom identifier as the provider name, ensuring consistent behavior across proprietary or self-hosted CI systems.
Essential Environment Variables
Two key environment variables control CI-specific behavior:
MAESTRO_CLI_NO_ANALYTICS – Set this to true to disable the analytics consent dialog. According to the source in maestro-cli/src/main/java/maestro/cli/analytics/Analytics.kt, this prevents the interactive prompt that would otherwise halt execution in non-interactive shells.
MDEV_CI – Forces CI mode detection when running on custom infrastructure or unsupported CI platforms.
CLI Flags for CI-Friendly Output
The TestCommand class in maestro-cli/src/main/java/maestro/cli/command/TestCommand.kt exposes flags that streamline artifact collection:
--flatten-debug-output (lines 158-161) – Writes all test artifacts directly into a single folder without timestamps or subdirectories, simplifying artifact upload configurations in CI systems.
--format junit – Produces JUnit XML reports that most CI platforms can parse for test result visualization.
--debug-output <path> – Specifies a deterministic location for screenshots, logs, and other debug artifacts.
Step-by-Step Integration
Follow this pattern to add Maestro to any CI pipeline:
- Install the Maestro CLI using the official installer or by extracting the pre-built distribution:
curl -fsSL "https://get.maestro.mobile.dev" | bash
- Configure environment variables to suppress interactive elements:
export MAESTRO_CLI_NO_ANALYTICS=true
- Execute tests with CI-optimized flags:
maestro test path/to/flow.yaml \
--flatten-debug-output \
--output ./maestro-output \
--format junit
- Upload artifacts to your CI platform's storage for failure analysis.
CI/CD Platform Configuration Examples
GitHub Actions
The mobile-dev-inc/Maestro repository uses this pattern in .github/workflows/test-e2e.yaml:
name: Maestro CI Demo
on:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Install Maestro
run: |
curl -fsSL "https://get.maestro.mobile.dev" | bash
echo "$HOME/.maestro/bin" >> $GITHUB_PATH
- name: Run Maestro tests
env:
MAESTRO_CLI_NO_ANALYTICS: true
run: |
maestro test ./e2e/workspaces/demo_app \
--flatten-debug-output \
--output ./maestro-output \
--format junit
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: maestro-test-results
path: ./maestro-output
CircleCI
For CircleCI, use the store_artifacts step after running Maestro:
version: 2.1
jobs:
maestro-test:
docker:
- image: cimg/android:2024.01
steps:
- checkout
- run:
name: Install Maestro
command: |
curl -fsSL "https://get.maestro.mobile.dev" | bash
echo 'export PATH="$HOME/.maestro/bin:$PATH"' >> $BASH_ENV
- run:
name: Run tests
command: |
export MAESTRO_CLI_NO_ANALYTICS=true
maestro test ./flows --flatten-debug-output --output ./results
- store_artifacts:
path: ./results
destination: maestro-output
GitLab CI
GitLab CI requires explicit artifact path definitions:
maestro-tests:
image: ubuntu:latest
before_script:
- apt-get update && apt-get install -y curl unzip openjdk-17-jdk
- curl -fsSL "https://get.maestro.mobile.dev" | bash
- export PATH="$HOME/.maestro/bin:$PATH"
script:
- export MAESTRO_CLI_NO_ANALYTICS=true
- maestro test ./app/flows --flatten-debug-output --output ./maestro-output --format junit
artifacts:
when: always
paths:
- ./maestro-output
reports:
junit: ./maestro-output/report.xml
Summary
-
Automatic Detection: Maestro identifies CI environments via
CiUtils.getCiProvider()inmaestro-cli/src/main/java/maestro/cli/util/CiUtils.kt, checking for variables likeGITHUB_ACTIONSandCIRCLECI. -
Non-Interactive Mode: Set
MAESTRO_CLI_NO_ANALYTICS=trueto disable analytics prompts and ensure headless execution. -
Deterministic Output: Use
--flatten-debug-outputfromTestCommand.ktto write artifacts to a single directory without timestamps, simplifying CI artifact collection. -
Custom CI Support: Export
MDEV_CI=your-ci-nameto force CI detection on unsupported or self-hosted platforms. -
JUnit Integration: Add
--format junitto generate XML reports compatible with GitHub Actions, GitLab CI, Jenkins, and other platforms.
Frequently Asked Questions
How does Maestro know it is running in a CI environment?
Maestro checks for standard CI provider environment variables in the CiUtils.getCiProvider() function. Located in maestro-cli/src/main/java/maestro/cli/util/CiUtils.kt (lines 5-19), this function maps variables like GITHUB_ACTIONS, CIRCLECI, and GITLAB_CI to normalized provider names. When any are detected, the CLI automatically disables progress bars and interactive prompts.
What happens if my CI provider is not supported?
Set the MDEV_CI environment variable to any non-empty value. As implemented in CiUtils.kt, this forces the CLI into CI mode regardless of the underlying platform. This ensures that UI-only features remain disabled and output remains machine-readable on custom runners or proprietary CI systems.
Why is my CI pipeline hanging at the analytics prompt?
Without the MAESTRO_CLI_NO_ANALYTICS=true environment variable, Maestro attempts to prompt for analytics consent via stdin. In non-interactive CI shells, this blocks indefinitely. The Analytics.kt file checks this variable to skip the prompt, allowing execution to proceed immediately.
How do I collect test artifacts consistently across CI runs?
Use the --flatten-debug-output flag available in TestCommand.kt (lines 158-161). This writes screenshots, logs, and other debug files directly into your specified output directory without timestamped subfolders. Combined with --output ./maestro-output, this creates a stable path for CI artifact uploaders to collect results after every test run.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →