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_ACTIONS
  • CIRCLECI
  • TEAMCITY_VERSION
  • GITLAB_CI
  • JENKINS_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:

  1. Install the Maestro CLI using the official installer or by extracting the pre-built distribution:
curl -fsSL "https://get.maestro.mobile.dev" | bash
  1. Configure environment variables to suppress interactive elements:
export MAESTRO_CLI_NO_ANALYTICS=true
  1. Execute tests with CI-optimized flags:
maestro test path/to/flow.yaml \
  --flatten-debug-output \
  --output ./maestro-output \
  --format junit
  1. 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() in maestro-cli/src/main/java/maestro/cli/util/CiUtils.kt, checking for variables like GITHUB_ACTIONS and CIRCLECI.

  • Non-Interactive Mode: Set MAESTRO_CLI_NO_ANALYTICS=true to disable analytics prompts and ensure headless execution.

  • Deterministic Output: Use --flatten-debug-output from TestCommand.kt to write artifacts to a single directory without timestamps, simplifying CI artifact collection.

  • Custom CI Support: Export MDEV_CI=your-ci-name to force CI detection on unsupported or self-hosted platforms.

  • JUnit Integration: Add --format junit to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →