Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
24612bc
feat(infrastructure): add managed Android Appium setup
MohabMohie Aug 14, 2026
0c897ec
test(android): add packaged and real acceptance gates
MohabMohie Aug 14, 2026
b882601
ci(android): gate managed emulator acceptance
MohabMohie Aug 14, 2026
0a0f13a
Merge remote-tracking branch 'origin/main' into ChaosEngine/setup-app…
MohabMohie Aug 14, 2026
3ca1c8f
test(android): await Windows child log release
MohabMohie Aug 14, 2026
09bb927
fix(android): scope sdk license consent to approved packages
MohabMohie Aug 14, 2026
294ffa7
fix(infrastructure): safely materialize Node archive links
MohabMohie Aug 14, 2026
2fce143
ci(android): expose managed install diagnostics
MohabMohie Aug 14, 2026
a9a2ad8
fix(cli): report nested setup failure causes
MohabMohie Aug 14, 2026
ac6e493
fix(android): use portable Node Unix layout
MohabMohie Aug 14, 2026
2da9076
fix(android): tolerate Appium JSON log preamble
MohabMohie Aug 14, 2026
cb6a70d
fix(android): restore SDK command executability
MohabMohie Aug 14, 2026
f999458
ci(android): provision emulator audio runtime
MohabMohie Aug 14, 2026
58e6154
fix(android): parse Appium version after diagnostics
MohabMohie Aug 14, 2026
0635e93
fix(android): verify AVD identity through emulator console
MohabMohie Aug 14, 2026
aebf963
test(android): accept canonical aapt2 banner
MohabMohie Aug 14, 2026
78a37e1
fix(android): rebuild Appium cache after publication
MohabMohie Aug 14, 2026
b05743a
ci(android): use cross-platform packaged plan path
MohabMohie Aug 14, 2026
70f5465
refactor(android): resolve quality audit findings
MohabMohie Aug 14, 2026
67418b5
fix(android): diagnose emulator acceleration
MohabMohie Aug 14, 2026
612706d
test(android): prove cross-process CLI lifecycle
MohabMohie Aug 14, 2026
adb7bd3
fix(mcp): discover shared Android toolchain
MohabMohie Aug 14, 2026
adb058d
fix(android): lease post-exec process identity
MohabMohie Aug 14, 2026
5e68d49
fix(android): verify exact AVD system image
MohabMohie Aug 14, 2026
8b3a63c
fix(setup): harden portable Node ZIP extraction
MohabMohie Aug 14, 2026
6a17aac
fix(android): bind lease command arguments
MohabMohie Aug 14, 2026
09e08e0
test(android): account for process argument visibility
MohabMohie Aug 14, 2026
da16e83
fix(android): reject emulator-reserved Appium ports
MohabMohie Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 94 additions & 1 deletion .github/workflows/e2eLocalTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
- MacOSX_Safari_Local
- Windows_Chrome_Local
- Windows_Managed_Lighthouse
- Ubuntu_Managed_Android
- Windows_SikuliX_Local
- Windows_Appium_Desktop_Local
- MacOSX_Chrome_Local
Expand Down Expand Up @@ -500,9 +501,101 @@ jobs:
job-name: Windows_Edge_Cucumber_Local
codecov-token: ${{ secrets.CODECOV_TOKEN }}

# Opt-in real acceptance for #4898. The packaged CLI performs the only installation
# mutation; a packaged CLI process starts the receipt-bound AVD/Appium lease, the engine
# reuses it for a real UiAutomator2 session, and a later CLI process owns final shutdown.
Ubuntu_Managed_Android:
if: github.event_name == 'workflow_dispatch' && (github.event.inputs.jobs == 'all' || contains(format(',{0},', github.event.inputs.jobs), ',Ubuntu_Managed_Android,'))
runs-on: ubuntu-22.04
timeout-minutes: 60
outputs:
job: ${{ steps.post_test_report.outputs.job }}
total: ${{ steps.post_test_report.outputs.total }}
passed: ${{ steps.post_test_report.outputs.passed }}
failed: ${{ steps.post_test_report.outputs.failed }}
broken: ${{ steps.post_test_report.outputs.broken }}
skipped: ${{ steps.post_test_report.outputs.skipped }}
duration: ${{ steps.post_test_report.outputs.duration }}
steps:
- name: Checkout Code
uses: actions/checkout@v7
- name: Setup Test Environment
uses: ./.github/actions/setup-test-env
with:
node-version: '24'
- name: Provision the Android emulator host runtime
run: |
if [ -e /dev/kvm ]; then sudo chmod 666 /dev/kvm; fi
sudo apt-get update
sudo apt-get install --yes libpulse0
- name: Package the setup CLI
run: mvn --batch-mode -pl shaft-cli -am package -DskipTests '-Dallure.automaticallyOpen=false' -Dgpg.skip
- name: Install the reviewed managed Android plan
shell: bash
run: |
cli_jar="$(find shaft-cli/target -maxdepth 1 -name 'shaft-cli-*[0-9].jar' -print -quit)"
test -n "$cli_jar"
cache_root="$RUNNER_TEMP/shaft-android-cache"
data_root="$cache_root/data"
plan="$RUNNER_TEMP/shaft-android-plan.json"
java -jar "$cli_jar" setup plan --profile MOBILE_ANDROID --mode MANAGED \
--output "$plan" --cache-root "$cache_root" --data-root "$data_root" \
--startup-timeout PT8M --shutdown-timeout PT1M
digest="$(python3 -c "import json,sys; print(json.load(open(sys.argv[1]))['digest'])" "$plan")"
if ! java -jar "$cli_jar" setup install --plan "$plan" --approve "$digest" \
--accept-license android-sdk-license --cache-root "$cache_root" --data-root "$data_root" \
--startup-timeout PT8M --shutdown-timeout PT1M; then
install_log="$data_root/state/logs/mobile-android-install.log"
test ! -f "$install_log" || cat "$install_log"
exit 1
fi
- name: Start the owned runtime from the packaged CLI
shell: bash
run: |
cli_jar="$(find shaft-cli/target -maxdepth 1 -name 'shaft-cli-*[0-9].jar' -print -quit)"
cache_root="$RUNNER_TEMP/shaft-android-cache"
data_root="$cache_root/data"
plan="$RUNNER_TEMP/shaft-android-plan.json"
digest="$(python3 -c "import json,sys; print(json.load(open(sys.argv[1]))['digest'])" "$plan")"
java -jar "$cli_jar" setup start --plan "$plan" --approve "$digest" \
--accept-license android-sdk-license --cache-root "$cache_root" --data-root "$data_root" \
--startup-timeout PT8M --shutdown-timeout PT1M
test -s "$data_root/state/mobile-android-runtime.json"
- name: Run real emulator, UiAutomator2, and aapt2 acceptance
continue-on-error: true
run: >-
mvn --batch-mode -pl shaft-engine -am test
'-Dtest=testPackage.ManagedAndroidE2ETest'
-DrunManagedAndroidE2E=true
-Dinfrastructure.mode=MANAGED
-Dinfrastructure.profile=MOBILE_ANDROID
-Dinfrastructure.cacheDirectory=${{ runner.temp }}/shaft-android-cache
-Dinfrastructure.startupTimeout=PT8M
-Dinfrastructure.shutdownTimeout=PT1M
-Dallure.automaticallyOpen=false
-Dgpg.skip=true
- name: Stop the owned runtime from a later packaged CLI process
if: always()
shell: bash
run: |
cli_jar="$(find shaft-cli/target -maxdepth 1 -name 'shaft-cli-*[0-9].jar' -print -quit)"
cache_root="$RUNNER_TEMP/shaft-android-cache"
data_root="$cache_root/data"
test -s "$data_root/state/mobile-android-runtime.json"
java -jar "$cli_jar" setup stop --profile MOBILE_ANDROID \
--cache-root "$cache_root" --data-root "$data_root" --shutdown-timeout PT1M
test ! -e "$data_root/state/mobile-android-runtime.json"
- name: Post-Test Report and Check
id: post_test_report
if: always()
uses: ./.github/actions/post-test-report
with:
job-name: Ubuntu_Managed_Android
codecov-token: ${{ secrets.CODECOV_TOKEN }}

notify_local_e2e_tests_failure:
name: Notify on nightly failure
needs: [ Windows_Edge_Local, MacOSX_Safari_Local, Windows_Chrome_Local, Windows_Managed_Lighthouse, Windows_SikuliX_Local, Windows_Appium_Desktop_Local, MacOSX_Chrome_Local, Windows_Edge_Cucumber_Local ]
needs: [ Windows_Edge_Local, MacOSX_Safari_Local, Windows_Chrome_Local, Windows_Managed_Lighthouse, Ubuntu_Managed_Android, Windows_SikuliX_Local, Windows_Appium_Desktop_Local, MacOSX_Chrome_Local, Windows_Edge_Cucumber_Local ]
if: always()
runs-on: ubuntu-22.04
timeout-minutes: 5
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/pr-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ jobs:
- '.github/workflows/e2eLocalTests.yml'
- 'tests/scripts/test_ocr_infrastructure_boundary.py'
- 'tests/scripts/test_lighthouse_infrastructure_boundary.py'
- 'tests/scripts/test_android_infrastructure_boundary.py'
infra:
- '.github/workflows/pr-gate.yml'
# Composite actions this gate's jobs call (issue #4440 added
Expand Down Expand Up @@ -591,6 +592,10 @@ jobs:
java -jar shaft-cli/target/shaft-cli-*[0-9].jar --help
java -jar shaft-cli/target/shaft-cli-*[0-9].jar setup --help
java -jar shaft-cli/target/shaft-cli-*[0-9].jar setup catalog --json
android_plan="$RUNNER_TEMP/shaft-android-plan.json"
java -jar shaft-cli/target/shaft-cli-*[0-9].jar setup plan --profile MOBILE_ANDROID \
--mode MANAGED --offline --output "$android_plan"
python3 -c "import json,sys; p=json.load(open(sys.argv[1])); assert len(p['actions']) == 6; assert 'android-sdk-license' in p['actions'][4]['requiredLicenses']" "$android_plan"

capture-e2e:
name: SHAFT Capture Browser E2E
Expand Down Expand Up @@ -854,7 +859,8 @@ jobs:
python3 -m unittest
tests.scripts.test_pilot_module_boundary
tests.scripts.test_ocr_infrastructure_boundary
tests.scripts.test_lighthouse_infrastructure_boundary -v
tests.scripts.test_lighthouse_infrastructure_boundary
tests.scripts.test_android_infrastructure_boundary -v

# Issue #4071: a TestNG suite XML file that no pom, workflow, or script
# references is invisible -- unlike a failing test, nothing reports it, so
Expand Down
4 changes: 2 additions & 2 deletions scripts/ci/validate_quality_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,10 +555,10 @@ def validate_quality_configuration(root: Path = ROOT) -> list[str]:
e2e_workflow.count('"-DincludeVisualTestRuntime"')
+ local_e2e_workflow.count('"-DincludeVisualTestRuntime"')
)
if grid_install_count != 4 or local_install_count != 4 or activation_count != 8:
if grid_install_count != 4 or local_install_count != 4 or activation_count != 10:
errors.append(
"e2eTests.yml and e2eLocalTests.yml must prepare and activate the visual test runtime "
"for 4 grid/cloud and 4 local broad browser jobs"
"for 4 grid/cloud, 4 local broad-browser, and 2 OCR acceptance jobs"
)
for required_local_flow in (
"Windows_SikuliX_Local",
Expand Down
Loading
Loading