Maestro Deck
Guides

GitHub Action

Run your Maestro flows on MaestroDeck Cloud from CI with a single GitHub Actions step. Setup, inputs, outputs and full workflow examples.

The official BlueShork/maestro-action lets you run your Maestro flows on MaestroDeck Cloud straight from GitHub Actions. One step uploads your app and flows, runs them on a real simulator or emulator, waits for the result, and fails the build if the tests fail. No runner to provision, no simulator to boot in CI.

- uses: BlueShork/maestro-action@v5
  with:
    api_key: ${{ secrets.MAESTRO_API_KEY }}
    platform: android
    app: build/app-release.apk
    flow: .maestro/

How it works

The action uploads your build and flow files to MaestroDeck Cloud, runs them on the cloud device pool, polls for the result, and exits 0 (passed) or 1 (failed or error) so your pipeline goes green or red accordingly. Android jobs dispatch instantly; iOS jobs run on the macOS worker pool. It's the same pipeline as the web dashboard, triggered from CI.

Two things are worth their own page: web testing, where the target is a URL rather than a build, and visual regression, where the run compares its screenshots against a bank of references you keep in the repo.

Because the run happens on MaestroDeck Cloud, your CI runner stays a plain ubuntu-latest box. You don't need macOS minutes or an Android emulator in the workflow.

Setup

1. Generate an API key

Open your MaestroDeck dashboard profile page, find the API keys section, and click Generate key. Copy it right away. it's shown only once and looks like mk_live_....

2. Add it as a repository secret

In your GitHub repo, go to Settings → Secrets and variables → Actions → New repository secret. Name it MAESTRO_API_KEY and paste the key. Never hard-code the key in your workflow file.

3. Add the step to a workflow

Create (or edit) a workflow under .github/workflows/, build your app artifact, then add the maestro-action step pointing at that artifact and your flows. See the examples below.

Inputs

InputRequiredDefaultDescription
api_keyyesYour MaestroDeck API key (mk_live_...). Always pass it via a secret.
platformyesios, android or web.
appfor ios / androidPath to the .apk (Android) or .app.zip (iOS). Ignored on web.
urlfor webThe site to test. See web testing.
flowyesPath or glob to your Maestro .yaml flow files, or a directory of them.
emailnoaccount emailSend the report to a specific address instead of your account email.
timeoutno1800Max seconds to wait for the result before giving up. Does not change the run's own server-side timeout.
bank_pathnoFolder of reference .png images. Enables visual regression.
app_namenoName under which to file the bank, grouping runs under Apps in the dashboard.
visual_strictno"false"Fail the step when the visual report shows a difference.
screen_sizeno1512x982Browser size for web runs, as {width}x{height}. Web only.

Outputs

OutputDescription
job_idThe created job id.
statusFinal status: passed, failed, or error.
report_urlLink to the full report in the dashboard.
visual_changedNumber of bank images whose capture differs from the reference. Empty when no bank was configured.
visual_missingNumber of bank images with no matching capture. Empty when no bank was configured.

Examples

Android

Build your APK in an earlier step, then hand its path to the action:

name: E2E
on: [push]
jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # ... build your APK into build/app-release.apk ...
      - uses: BlueShork/maestro-action@v5
        with:
          api_key: ${{ secrets.MAESTRO_API_KEY }}
          platform: android
          app: build/app-release.apk
          flow: .maestro/

iOS

Point app at a zipped .app bundle and platform at ios:

- uses: BlueShork/maestro-action@v5
  with:
    api_key: ${{ secrets.MAESTRO_API_KEY }}
    platform: ios
    app: build/MyApp.app.zip
    flow: .maestro/login.yaml

Using the outputs

Read report_url, status or job_id in later steps. Use if: always() so the link is printed even when the run fails:

- uses: BlueShork/maestro-action@v5
  id: maestro
  with:
    api_key: ${{ secrets.MAESTRO_API_KEY }}
    platform: android
    app: build/app-release.apk
    flow: .maestro/
- if: always()
  run: echo "Report: ${{ steps.maestro.outputs.report_url }}"

Notes

  • flow accepts a single file (.maestro/login.yaml), a glob (.maestro/*.yaml), or a directory (.maestro/, which picks up every .yaml / .yml inside).
  • Each step invocation consumes one run from your MaestroDeck quota.
  • The action needs curl and jq, both preinstalled on GitHub-hosted runners.
  • Pin to a version tag (@v5) for stable behaviour, or pin a full SHA if you want byte-for-byte reproducibility. @v1 predates web and visual regression support.