Fixing BCIT and in app tests in CI #406
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: In-App Message E2E Tests | |
| on: | |
| push: | |
| branches: [ InApp-Display-E2E ] | |
| pull_request: | |
| branches: [ InApp-Display-E2E, master, develop ] | |
| workflow_dispatch: # Allow manual triggering | |
| jobs: | |
| inapp-e2e-tests: | |
| name: In-App Message E2E Tests | |
| runs-on: macos-15-intel | |
| strategy: | |
| matrix: | |
| api-level: [34] # MVP testing on most relevant API level only | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| - name: Set up Android SDK | |
| uses: android-actions/setup-android@v2 | |
| - name: Create local.properties | |
| run: | | |
| echo "sdk.dir=$ANDROID_SDK_ROOT" > local.properties | |
| echo "ndk.dir=$ANDROID_SDK_ROOT/ndk" >> local.properties | |
| - name: Accept Android SDK Licenses | |
| run: | | |
| echo "Accepting Android SDK licenses..." | |
| yes | sdkmanager --licenses || true | |
| echo "SDK licenses accepted" | |
| - name: Setup Google Services Configuration | |
| run: | | |
| echo "Setting up Google Services configuration for CI..." | |
| # Ensure the google-services.json file exists for the build | |
| if [ ! -f "integration-tests/google-services.json" ]; then | |
| echo "Creating google-services.json from template..." | |
| cp integration-tests/google-services.json.template integration-tests/google-services.json | |
| fi | |
| echo "Google Services configuration ready" | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-gradle- | |
| - name: Pre-download Gradle and Build (Parallel with Emulator) | |
| run: | | |
| echo "Pre-downloading Gradle and building while emulator boots..." | |
| # Download Gradle wrapper in background | |
| ./gradlew --version & | |
| # Start building APKs in background | |
| ./gradlew :integration-tests:assembleDebug :integration-tests:assembleDebugAndroidTest --no-daemon & | |
| echo "Build started in background..." | |
| - name: Run UI Tests with Emulator (Intel / x86_64) | |
| uses: ReactiveCircus/android-emulator-runner@v2 | |
| with: | |
| api-level: ${{ matrix.api-level }} | |
| target: google_apis | |
| arch: x86_64 | |
| profile: pixel_6 | |
| cores: 2 | |
| ram-size: 3072M | |
| heap-size: 576M | |
| force-avd-creation: true | |
| disable-animations: true | |
| emulator-boot-timeout: 900 | |
| emulator-options: -no-window -no-snapshot -gpu swiftshader_indirect -no-boot-anim -camera-back none -partition-size 6000 | |
| pre-emulator-launch-script: | | |
| # Clean + start adb after platform-tools exist (avoids tcp:5037 noise) | |
| adb kill-server >/dev/null 2>&1 || true | |
| adb start-server | |
| script: | | |
| # SDK-170 OBSERVABILITY: capture diagnostics that survive the action exit. | |
| # The android-emulator-runner kills the emulator on its way out, so any | |
| # adb-dependent capture MUST happen before this script returns. We write | |
| # everything under $GITHUB_WORKSPACE so a later step can upload it. | |
| DIAG_DIR="$GITHUB_WORKSPACE/integration-tests/build/diagnostics" | |
| mkdir -p "$DIAG_DIR" | |
| capture_diag() { | |
| local label="$1" | |
| local prefix="$2" | |
| echo "=== diag capture: $label ===" | |
| { | |
| echo "# label: $label" | |
| echo "# t: $(date -u +%FT%TZ)" | |
| echo | |
| echo "## adb devices" | |
| adb devices 2>&1 | |
| echo | |
| echo "## top activities" | |
| adb shell dumpsys activity activities 2>&1 | head -200 | |
| echo | |
| echo "## window state (focused app + visible windows)" | |
| adb shell dumpsys window 2>&1 | head -200 | |
| echo | |
| echo "## connectivity (active default network, link addresses, dns)" | |
| adb shell dumpsys connectivity 2>&1 | head -120 | |
| echo | |
| echo "## meminfo (system_server + integration tests)" | |
| adb shell dumpsys meminfo 2>&1 | head -80 | |
| echo | |
| echo "## installed iterable packages" | |
| adb shell pm list packages 2>&1 | grep iterable || true | |
| echo | |
| echo "## boot props" | |
| adb shell getprop sys.boot_completed dev.bootcomplete init.svc.netd net.dns1 ro.build.version.release ro.build.version.sdk 2>&1 | head -10 | |
| } > "$DIAG_DIR/${prefix}-state.txt" 2>&1 | |
| # UiAutomator hierarchy and screenshot — the smoking gun for "button not found" | |
| adb shell uiautomator dump /sdcard/hierarchy.xml >/dev/null 2>&1 || true | |
| adb pull /sdcard/hierarchy.xml "$DIAG_DIR/${prefix}-hierarchy.xml" >/dev/null 2>&1 || echo "(no hierarchy)" | |
| adb shell screencap -p /sdcard/screenshot.png >/dev/null 2>&1 || true | |
| adb pull /sdcard/screenshot.png "$DIAG_DIR/${prefix}-screenshot.png" >/dev/null 2>&1 || echo "(no screenshot)" | |
| } | |
| echo "Emulator is ready! Running tests..." | |
| echo "Setting up permissions..." | |
| adb shell pm grant com.iterable.integration.tests android.permission.POST_NOTIFICATIONS || true | |
| adb shell pm grant com.iterable.integration.tests android.permission.INTERNET || true | |
| adb shell pm grant com.iterable.integration.tests android.permission.ACCESS_NETWORK_STATE || true | |
| adb shell pm grant com.iterable.integration.tests android.permission.WAKE_LOCK || true | |
| echo "Running In-App Message MVP test..." | |
| echo "Debug: Checking if APKs are ready..." | |
| ls -la integration-tests/build/outputs/apk/ || echo "APK directory not found" | |
| echo "Debug: Verifying API keys are set..." | |
| echo "ITERABLE_API_KEY length: ${#ITERABLE_API_KEY}" | |
| echo "ITERABLE_SERVER_API_KEY length: ${#ITERABLE_SERVER_API_KEY}" | |
| echo "ITERABLE_TEST_USER_EMAIL: $ITERABLE_TEST_USER_EMAIL" | |
| # Snapshot pre-test device state. If tests fail because the activity never | |
| # foregrounded, this captures what was on screen *before* we even ran. | |
| capture_diag "pre-test" "00-pre-test" | |
| # Stream full logcat to the workspace so we get an artifact even on success. | |
| adb logcat -c >/dev/null 2>&1 || true | |
| adb logcat > "$DIAG_DIR/10-logcat-full.txt" & | |
| LOGCAT_PID=$! | |
| GRADLE_EXIT=0 | |
| ./gradlew :integration-tests:connectedDebugAndroidTest \ | |
| -Pandroid.testInstrumentationRunnerArguments.class=com.iterable.integration.tests.InAppMessageIntegrationTest#testInAppMessageMVP \ | |
| --stacktrace --no-daemon || GRADLE_EXIT=$? | |
| # Stop logcat ASAP so post-test capture isn't entangled with it. | |
| kill $LOGCAT_PID 2>/dev/null || true | |
| wait $LOGCAT_PID 2>/dev/null || true | |
| # Always capture post-test state — useful on success too (proves the test | |
| # really did exercise the SDK and surface campaigns). | |
| capture_diag "post-test" "20-post-test" | |
| # Filtered logcat for fast triage; full logcat is also uploaded. | |
| grep -E 'IterableApi|IterableRequest|IterableInApp|IterableEmbedded|IntegrationMainActivity|BaseIntegrationTest|InAppMessageIntegrationTest|PushNotificationIntegrationTest|EmbeddedMessageIntegrationTest|DeepLinkIntegrationTest|FATAL|AndroidRuntime|ANR' \ | |
| "$DIAG_DIR/10-logcat-full.txt" > "$DIAG_DIR/11-logcat-filtered.txt" 2>/dev/null || true | |
| echo | |
| echo "=== diagnostics summary ===" | |
| ls -la "$DIAG_DIR" | |
| echo | |
| echo "Last 50 logcat lines (full file uploaded as artifact):" | |
| tail -50 "$DIAG_DIR/10-logcat-full.txt" || true | |
| if [ "$GRADLE_EXIT" != "0" ]; then | |
| echo "::error::Test gradle task failed with exit code $GRADLE_EXIT — see e2e-diagnostics-api-${{ matrix.api-level }} artifact" | |
| exit "$GRADLE_EXIT" | |
| fi | |
| env: | |
| ITERABLE_API_KEY: ${{ secrets.BCIT_ITERABLE_API_KEY }} | |
| ITERABLE_SERVER_API_KEY: ${{ secrets.BCIT_ITERABLE_SERVER_API_KEY }} | |
| ITERABLE_TEST_USER_EMAIL: ${{ secrets.BCIT_ITERABLE_TEST_USER_EMAIL }} | |
| - name: Upload E2E diagnostics | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-diagnostics-api-${{ matrix.api-level }} | |
| path: | | |
| integration-tests/build/diagnostics/ | |
| integration-tests/build/reports/ | |
| integration-tests/build/outputs/ | |
| if-no-files-found: warn | |
| retention-days: 7 | |
| # test-summary: | |
| # name: Test Summary | |
| # runs-on: ubuntu-latest | |
| # needs: inapp-e2e-tests | |
| # if: always() | |
| # steps: | |
| # - name: Checkout code | |
| # uses: actions/checkout@v4 | |
| # - name: Download Test Results | |
| # uses: actions/download-artifact@v4 | |
| # with: | |
| # name: inapp-e2e-test-results-api-34 | |
| # path: test-results/ | |
| # - name: Generate Test Summary | |
| # run: | | |
| # echo "## In-App Message E2E Test Results" >> $GITHUB_STEP_SUMMARY | |
| # echo "" >> $GITHUB_STEP_SUMMARY | |
| # echo "### Test Execution Summary" >> $GITHUB_STEP_SUMMARY | |
| # echo "- **Branch**: InApp-Display-E2E" >> $GITHUB_STEP_SUMMARY | |
| # echo "- **API Level Tested**: 34" >> $GITHUB_STEP_SUMMARY | |
| # echo "- **Test Method**: testInAppMessageMVP" >> $GITHUB_STEP_SUMMARY | |
| # echo "- **Test Type**: E2E Integration Test" >> $GITHUB_STEP_SUMMARY | |
| # echo "" >> $GITHUB_STEP_SUMMARY | |
| # echo "### E2E Test Scenarios" >> $GITHUB_STEP_SUMMARY | |
| # echo "- ✅ User Sign-in Verification" >> $GITHUB_STEP_SUMMARY | |
| # echo "- ✅ In-App Message Trigger" >> $GITHUB_STEP_SUMMARY | |
| # echo "- ✅ Message Display Verification" >> $GITHUB_STEP_SUMMARY | |
| # echo "- ✅ Button Click Interaction" >> $GITHUB_STEP_SUMMARY | |
| # echo "- ✅ Message Dismissal" >> $GITHUB_STEP_SUMMARY | |
| # echo "" >> $GITHUB_STEP_SUMMARY | |
| # echo "### Artifacts Available" >> $GITHUB_STEP_SUMMARY | |
| # echo "- Test execution reports" >> $GITHUB_STEP_SUMMARY | |
| # echo "- Code coverage reports" >> $GITHUB_STEP_SUMMARY | |
| # echo "- Debug screenshots" >> $GITHUB_STEP_SUMMARY | |
| # echo "- Detailed test logs" >> $GITHUB_STEP_SUMMARY |