Repository navigation
172 lines (159 loc) · 7.27 KB
/
Copy pathmaestro.yml
File metadata and controls
172 lines (159 loc) · 7.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
name: Maestro E2E
# Real-backend E2E against the shared test account, so it is not wired to every PR by
# default: run it on demand (choose tags) and nightly (smoke). To gate PRs, add a
# `pull_request:` trigger below — note it needs the test-account secrets, so it won't run
# on fork PRs.
on:
workflow_dispatch:
inputs:
tags:
description: "Maestro include-tags (e.g. smoke, tipping, gate)"
default: "smoke"
exclude_tags:
description: "Maestro exclude-tags (side-effecting flows excluded by default)"
default: "spends-funds,creates-account"
minify:
description: "Run against an R8-minified build, an unminified one, or both in turn"
type: choice
default: "true"
options: ["true", "false", "both"]
schedule:
- cron: "37 7 * * *" # nightly, off the top of the hour
concurrency:
group: maestro-${{ github.ref }}
cancel-in-progress: true
jobs:
# `minify: both` has to become a matrix before the job starts, and a matrix cannot be
# built from an input inline. Scheduled runs get no input, so they fall through to the
# minified build — that is the one that catches a broken keep rule.
variants:
runs-on: ubuntu-latest
outputs:
minify: ${{ steps.pick.outputs.minify }}
steps:
- id: pick
run: |
case "${{ github.event.inputs.minify || 'true' }}" in
both) echo 'minify=["true","false"]' >> "$GITHUB_OUTPUT" ;;
false) echo 'minify=["false"]' >> "$GITHUB_OUTPUT" ;;
*) echo 'minify=["true"]' >> "$GITHUB_OUTPUT" ;;
esac
maestro:
name: Maestro E2E (${{ github.event.inputs.tags || 'smoke' }}, minify=${{ matrix.minify }})
needs: variants
runs-on: ubuntu-24.04 # ruby/setup-ruby has no Ruby 2.7 build for ubuntu-26.04
timeout-minutes: 60
strategy:
# One at a time: every flow signs into the same shared test account, so two runners
# would fight over its balance and session.
max-parallel: 1
fail-fast: false
matrix:
minify: ${{ fromJSON(needs.variants.outputs.minify) }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup Java env
uses: actions/setup-java@v3
with:
java-version: "21"
distribution: "corretto"
cache: "gradle"
- name: Setup Ruby env
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7.2
bundler-cache: true
# Build prerequisites (same as the unit-test CI job).
- name: Decode Google Services JSON file
uses: timheuer/base64-to-file@v1
with:
fileName: google-services.json
fileDir: ./apps/flipcash/app/src
encodedString: ${{ secrets.FLIPCASH2_GOOGLE_SERVICES }}
- name: Setup local.properties API keys
run: |
{
echo "BUGSNAG_API_KEY=\"${{ secrets.FLIPCASH_BUGSNAG_API_KEY }}\""
echo "MIXPANEL_API_KEY=\"${{ secrets.FLIPCASH_MIXPANEL_API_KEY }}\""
echo "COINBASE_ONRAMP_API_KEY=${{ secrets.COINBASE_ONRAMP_API_KEY }}"
echo "GOOGLE_CLOUD_PROJECT_NUMBER=${{ secrets.GOOGLE_CLOUD_PROJECT_NUMBER }}"
} >> ./local.properties
- name: Install Maestro CLI
run: |
# Pinned: the installer takes the latest release otherwise. 2.11.0 is what the
# nightly has run since 2026-09-29.
export MAESTRO_VERSION=2.11.0
curl -fsSL "https://get.maestro.mobile.dev" | bash
echo "$HOME/.maestro/bin" >> "$GITHUB_PATH"
# KVM is required for a fast x86_64 emulator on GitHub-hosted Linux runners.
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
# Build the APK before the emulator exists. Compiling and R8-minifying the app takes
# ~10 minutes and several GB of heap; done inside the emulator step it competes with
# the running guest for the runner's memory, and since 2026-10-08 the emulator has
# exited mid-flow (adb: offline, then device not found). Stopping the daemons after
# the build returns that memory before the guest starts; the lane's installDebug
# then finds every task up to date.
- name: Build debug APK
run: |
./gradlew :apps:flipcash:app:assembleDebug -p .
./gradlew --stop
env:
DEBUG_MINIFY: ${{ matrix.minify }}
- name: Run Maestro suite on emulator
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
profile: pixel_6
ram-size: 4096M
heap-size: 576M
force-avd-creation: false
emulator-options: -no-window -gpu swangle_indirect -no-snapshot -noaudio -no-boot-anim
disable-animations: true
# logcat runs alongside so the lines before an emulator exit survive in the artifact.
script: |
adb wait-for-device
# The AVD boots with 3-button navigation, whose Back key sits over the bottom row of
# the chat list: a tap on a contact there backgrounded the app. Real devices use
# gestures, and the app is laid out edge-to-edge for them.
adb shell cmd overlay enable com.android.internal.systemui.navbar.gestural
adb shell cmd overlay list | grep -i navbar || true
adb logcat -v threadtime > "$GITHUB_WORKSPACE/logcat.txt" &
bundle exec fastlane android flipcash_maestro
env:
MAESTRO_TAGS: ${{ github.event.inputs.tags || 'smoke' }}
MAESTRO_EXCLUDE_TAGS: ${{ github.event.inputs.exclude_tags || 'spends-funds,creates-account' }}
# Read by tryReadProperty in apps/flipcash/app/build.gradle.kts. local.properties
# wins over the environment there, and the step above never writes this key, so the
# value set here is the one Gradle sees. UI_TESTABLE stays true either way, since it
# is off only for the shipping `release` variant.
DEBUG_MINIFY: ${{ matrix.minify }}
# Test-account credentials (map GitHub secrets -> the env vars run.sh reads).
SEED_PHRASE: ${{ secrets.MAESTRO_SEED_PHRASE }}
LOGIN_DEEPLINK: ${{ secrets.MAESTRO_LOGIN_DEEPLINK }}
TIPCARD_DEEPLINK: ${{ secrets.MAESTRO_TIPCARD_DEEPLINK }}
LOGIN_USERNAME: ${{ secrets.MAESTRO_LOGIN_USERNAME }}
USDF_ONLY_DEEPLINK: ${{ secrets.MAESTRO_USDF_ONLY_DEEPLINK }}
CONTACT_NAME: ${{ secrets.MAESTRO_CONTACT_NAME }}
CONTACT_PHONE: ${{ secrets.MAESTRO_CONTACT_PHONE }}
# An emulator killed by the host leaves no trace in the step log; the kernel log does.
- name: Kernel log (OOM / qemu)
if: failure()
run: sudo dmesg | grep -i -E "out of memory|oom-kill|killed process|qemu" | tail -20 || true
- name: Upload Maestro report
if: always()
uses: actions/upload-artifact@v4
with:
name: maestro-report-minify-${{ matrix.minify }}
path: |
maestro-report.xml
logcat.txt
~/.maestro/tests/**
if-no-files-found: ignore