|
name: E2E |
|
|
|
on: |
|
push: |
|
branches: [main] |
|
pull_request: |
|
branches: [main] |
|
workflow_dispatch: |
|
|
|
jobs: |
|
coverage: |
|
# Runs first; fast static check that gates the long device jobs so |
|
# missing demos / flows fail before the emulator boots. |
|
runs-on: ubuntu-latest |
|
steps: |
|
- name: Checkout |
|
uses: actions/checkout@v4 |
|
- name: Set up Python |
|
uses: actions/setup-python@v5 |
|
with: |
|
python-version: '3.11' |
|
- name: Check E2E coverage of pythonnative.__all__ |
|
run: python scripts/check-e2e-coverage.py |
|
|
|
e2e-android: |
|
needs: coverage |
|
runs-on: ubuntu-latest |
|
timeout-minutes: 30 |
|
# GitHub-hosted Android emulators grow unstable after ~15 minutes of |
|
# sustained Maestro driving and start reporting "device offline" / |
|
# "device not found" mid-run (the emulator VM, not the app, dies). |
|
# The full 60-flow suite reliably crosses that threshold around the |
|
# ~35th flow. Sharding the run into a few balanced groups, each on |
|
# its own freshly booted emulator, keeps every session well under |
|
# the limit, and parallelizes the Android pass as a bonus. Groups are |
|
# sized so none exceeds ~15 flows; ``components`` (28 flows after the |
|
# gesture/animated additions) crossed the ceiling at ~flow 26, so it |
|
# runs as two halves. ``fail-fast: false`` so one shard's failure |
|
# still lets the others report. |
|
strategy: |
|
fail-fast: false |
|
matrix: |
|
include: |
|
- name: components-a |
|
suites: components-a |
|
- name: components-b |
|
suites: components-b |
|
- name: hooks-nav-gestures |
|
suites: hooks navigation gestures |
|
- name: layout-styling-anim-misc |
|
suites: layout styling animations misc |
|
|
|
name: e2e-android (${{ matrix.name }}) |
|
|
|
steps: |
|
- name: Checkout |
|
uses: actions/checkout@v4 |
|
|
|
- name: Set up Python |
|
uses: actions/setup-python@v5 |
|
with: |
|
python-version: '3.11' |
|
|
|
- name: Set up Java 17 |
|
uses: actions/setup-java@v4 |
|
with: |
|
distribution: 'temurin' |
|
java-version: '17' |
|
|
|
- name: Install PythonNative |
|
run: pip install -e . |
|
|
|
- name: Install Maestro |
|
run: | |
|
curl -Ls "https://get.maestro.mobile.dev" | bash |
|
echo "$HOME/.maestro/bin" >> $GITHUB_PATH |
|
|
|
- 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 |
|
|
|
- name: Build, install, and run E2E tests |
|
uses: reactivecircus/android-emulator-runner@v2 |
|
with: |
|
api-level: 31 |
|
arch: x86_64 |
|
script: bash -lc "./scripts/run-e2e.sh android ${{ matrix.suites }}" |
|
|
|
# Maestro writes per-flow debug output (command log, view-hierarchy |
|
# dumps, failure screenshots) under ~/.maestro/tests. Surface it when |
|
# a shard fails so CI-only failures are diagnosable without guesswork. |
|
- name: Upload Maestro debug output |
|
if: failure() |
|
uses: actions/upload-artifact@v4 |
|
with: |
|
name: maestro-debug-android-${{ matrix.name }} |
|
path: ~/.maestro/tests/ |
|
if-no-files-found: ignore |
|
retention-days: 7 |
|
|
|
e2e-ios: |
|
needs: coverage |
|
runs-on: macos-latest |
|
timeout-minutes: 40 |
|
# iOS simulators are stable for the full suite (unlike the Android |
|
# emulator; see the e2e-android note), so this split is purely a |
|
# speed optimization: the iOS Maestro run is ~22 minutes and is the |
|
# critical path for the whole E2E workflow. Sharding it across three |
|
# simulators (same balanced groups as Android) runs them in parallel |
|
# and roughly halves wall-clock time. macOS minutes are free on this |
|
# public repo, so the extra per-shard build/boot overhead is fine. |
|
# ``fail-fast: false`` so one shard's failure still lets the others |
|
# report. |
|
strategy: |
|
fail-fast: false |
|
matrix: |
|
include: |
|
- name: components |
|
suites: components |
|
- name: hooks-nav-gestures |
|
suites: hooks navigation gestures |
|
- name: layout-styling-anim-misc |
|
suites: layout styling animations misc |
|
|
|
name: e2e-ios (${{ matrix.name }}) |
|
|
|
steps: |
|
- name: Checkout |
|
uses: actions/checkout@v4 |
|
|
|
- name: Set up Python |
|
uses: actions/setup-python@v5 |
|
with: |
|
python-version: '3.11' |
|
|
|
- name: Install PythonNative |
|
run: pip install -e . |
|
|
|
- name: Install Maestro and idb |
|
run: | |
|
curl -Ls "https://get.maestro.mobile.dev" | bash |
|
echo "$HOME/.maestro/bin" >> $GITHUB_PATH |
|
# Homebrew refuses formulae from untrusted third-party taps by |
|
# default; trust the tap explicitly before installing. |
|
brew tap facebook/fb && brew trust facebook/fb && brew install idb-companion |
|
|
|
- name: Build and run E2E tests |
|
run: ./scripts/run-e2e.sh ios ${{ matrix.suites }} |
|
env: |
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
# Maestro writes per-flow debug output (command log, view-hierarchy |
|
# dumps, failure screenshots) under ~/.maestro/tests. Surface it when |
|
# a shard fails so CI-only failures are diagnosable without guesswork. |
|
- name: Upload Maestro debug output |
|
if: failure() |
|
uses: actions/upload-artifact@v4 |
|
with: |
|
name: maestro-debug-ios-${{ matrix.name }} |
|
path: ~/.maestro/tests/ |
|
if-no-files-found: ignore |
|
retention-days: 7 |