Weekly WebView Tests #35
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: Weekly WebView Tests | |
| on: | |
| schedule: | |
| # Run every Sunday at 2 AM UTC | |
| - cron: '0 2 * * 0' | |
| workflow_dispatch: | |
| inputs: | |
| upload_results: | |
| description: 'Upload results to GitHub' | |
| required: false | |
| default: true | |
| type: boolean | |
| jobs: | |
| test-android-webview: | |
| name: Android WebView | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| api-level: [34] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Setup Java | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| - name: Setup Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: Clone and build Android app | |
| run: | | |
| npm run setup:android-app | |
| cd apps/CanIAndroidWebView | |
| chmod +x gradlew | |
| ./gradlew assembleDebug --no-daemon | |
| - 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: Run tests on Android emulator | |
| uses: reactivecircus/android-emulator-runner@v2 | |
| with: | |
| api-level: ${{ matrix.api-level }} | |
| arch: x86_64 | |
| profile: pixel_5 | |
| disable-animations: true | |
| emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim | |
| script: | | |
| adb install -r apps/CanIAndroidWebView/app/build/outputs/apk/debug/app-debug.apk | |
| adb shell settings put global window_animation_scale 0 | |
| adb shell settings put global transition_animation_scale 0 | |
| adb shell settings put global animator_duration_scale 0 | |
| npm run test:android | |
| - name: Generate app token for results upload | |
| if: always() && (github.event_name == 'schedule' || inputs.upload_results == true) | |
| id: app-token-android | |
| uses: actions/create-github-app-token@v2 | |
| with: | |
| app-id: ${{ secrets.RESULTS_APP_ID }} | |
| private-key: ${{ secrets.RESULTS_APP_PRIVATE_KEY }} | |
| owner: WebView-CG | |
| repositories: webview-bcd-results | |
| - name: Upload results to webview-bcd-results | |
| if: always() && (github.event_name == 'schedule' || inputs.upload_results == true) | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token-android.outputs.token }} | |
| run: | | |
| if [ -f test-results/android-results.json ]; then | |
| echo "📁 Found results file" | |
| cat test-results/android-results.json | head -20 | |
| if [ -z "$GITHUB_TOKEN" ]; then | |
| echo "❌ App token not generated - skipping upload" | |
| echo "⚠️ Configure RESULTS_APP_ID and RESULTS_APP_PRIVATE_KEY secrets to enable automatic uploads" | |
| exit 0 | |
| fi | |
| echo "📤 Uploading results..." | |
| npm run upload-results test-results/android-results.json | |
| echo "✅ Results uploaded for Android API ${{ matrix.api-level }}" | |
| else | |
| echo "⚠️ No results file found at test-results/android-results.json" | |
| ls -la test-results/ || echo "test-results directory doesn't exist" | |
| fi | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: android-api-${{ matrix.api-level }}-results | |
| path: | | |
| test-results/ | |
| playwright-report/ | |
| retention-days: 30 | |
| test-ios-webview: | |
| name: iOS WKWebView | |
| runs-on: macos-26 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - ios-version: '26.0.1' | |
| xcode-version: '26.0.1' | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Install Appium drivers | |
| run: | | |
| npx appium driver install xcuitest | |
| npx appium driver list --installed | |
| - name: Start Appium server | |
| run: | | |
| echo "Starting Appium server..." | |
| npx appium --port 4723 > appium.log 2>&1 & | |
| APPIUM_PID=$! | |
| echo "APPIUM_PID=$APPIUM_PID" >> $GITHUB_ENV | |
| echo "Appium started with PID $APPIUM_PID" | |
| # Wait for Appium to be ready | |
| for i in {1..30}; do | |
| if curl -s http://localhost:4723/status > /dev/null; then | |
| echo "✓ Appium is ready" | |
| curl -s http://localhost:4723/status | jq '.' | |
| break | |
| else | |
| echo "Waiting for Appium... ($i/30)" | |
| sleep 1 | |
| fi | |
| done | |
| - name: Clone iOS app | |
| run: npm run setup:ios-app | |
| - name: Select Xcode version | |
| run: | | |
| sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode-version }}.app/Contents/Developer | |
| xcodebuild -version | |
| - name: Install iOS Simulator runtime | |
| run: | | |
| sudo xcodebuild -downloadPlatform iOS | |
| xcrun simctl list runtimes | |
| - name: List available simulators | |
| run: xcrun simctl list devices available | |
| - name: Build iOS app | |
| run: | | |
| xcodebuild -project apps/CanIWKWebView/CanIWKWebView.xcodeproj \ | |
| -scheme CanIWKWebView \ | |
| -configuration Debug \ | |
| -sdk iphonesimulator \ | |
| -destination 'generic/platform=iOS Simulator' \ | |
| -derivedDataPath ${{ github.workspace }}/build \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| TARGETED_DEVICE_FAMILY=1 | |
| echo "Built artifacts:" | |
| find ${{ github.workspace }}/build/Build/Products/Debug-iphonesimulator -name "*.app" -type d | |
| - name: Boot simulator and install app | |
| run: | | |
| APP_PATH=$(find ${{ github.workspace }}/build/Build/Products/Debug-iphonesimulator -name "*.app" -type d | head -1) | |
| if [ -z "$APP_PATH" ]; then | |
| echo "❌ No .app bundle found in Debug-iphonesimulator" | |
| exit 1 | |
| fi | |
| echo "Using app: $APP_PATH" | |
| SIMULATOR=$(xcrun simctl list devices available | grep "iPhone" | head -1 | sed -E 's/.*\(([A-F0-9-]+)\).*/\1/') | |
| echo "Using simulator: $SIMULATOR" | |
| xcrun simctl boot $SIMULATOR | |
| xcrun simctl install $SIMULATOR "$APP_PATH" | |
| echo "SIMULATOR_UDID=$SIMULATOR" >> $GITHUB_ENV | |
| - name: Verify app installation | |
| run: | | |
| echo "Checking if app is installed..." | |
| xcrun simctl listapps ${{ env.SIMULATOR_UDID }} | grep -i caniwebview || { | |
| echo "❌ App not found!" | |
| exit 1 | |
| } | |
| echo "✓ App is installed" | |
| - name: Launch iOS app via Appium | |
| run: | | |
| echo "App will be launched by Appium when tests start" | |
| echo "Bundle ID: com.caniwebview.wkwebview" | |
| echo "Simulator ready for testing" | |
| - name: Run tests | |
| run: npm run test:ios | |
| - name: Show Appium logs on failure | |
| if: failure() | |
| run: | | |
| echo "=== Appium Logs ===" | |
| cat appium.log || echo "No appium log found" | |
| echo "" | |
| echo "=== Process List ===" | |
| ps aux | grep -i appium || true | |
| - name: Generate app token for results upload | |
| if: always() && (github.event_name == 'schedule' || inputs.upload_results == 'true') | |
| id: app-token-ios | |
| uses: actions/create-github-app-token@v2 | |
| with: | |
| app-id: ${{ secrets.RESULTS_APP_ID }} | |
| private-key: ${{ secrets.RESULTS_APP_PRIVATE_KEY }} | |
| owner: WebView-CG | |
| repositories: webview-bcd-results | |
| - name: Upload results to webview-bcd-results | |
| if: always() && (github.event_name == 'schedule' || inputs.upload_results == 'true') | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token-ios.outputs.token }} | |
| run: | | |
| if [ -f test-results/ios-results.json ]; then | |
| echo "📁 Found results file" | |
| cat test-results/ios-results.json | head -20 | |
| if [ -z "$GITHUB_TOKEN" ]; then | |
| echo "❌ App token not generated - skipping upload" | |
| echo "⚠️ Configure RESULTS_APP_ID and RESULTS_APP_PRIVATE_KEY secrets to enable automatic uploads" | |
| exit 0 | |
| fi | |
| echo "📤 Uploading results..." | |
| npm run upload-results test-results/ios-results.json | |
| echo "✅ Results uploaded for iOS ${{ matrix.ios-version }}" | |
| else | |
| echo "⚠️ No results file found at test-results/ios-results.json" | |
| ls -la test-results/ || echo "test-results directory doesn't exist" | |
| fi | |
| - name: Upload test artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ios-${{ matrix.ios-version }}-results | |
| path: | | |
| test-results/ | |
| playwright-report/ | |
| retention-days: 30 | |
| summarize-results: | |
| name: Summarize Results | |
| runs-on: ubuntu-latest | |
| needs: [test-android-webview, test-ios-webview] | |
| if: always() | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: all-results | |
| - name: Create summary | |
| run: | | |
| echo "# WebView Test Results Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Date**: $(date -u +"%Y-%m-%d %H:%M UTC")" >> $GITHUB_STEP_SUMMARY | |
| echo "**Run**: [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Check if jobs succeeded | |
| ANDROID_SUCCESS="${{ needs.test-android-webview.result == 'success' }}" | |
| IOS_SUCCESS="${{ needs.test-ios-webview.result == 'success' }}" | |
| echo "## Android Results" >> $GITHUB_STEP_SUMMARY | |
| for dir in all-results/android-*; do | |
| if [ -d "$dir" ]; then | |
| api=$(basename "$dir" | sed 's/android-api-\([0-9]*\)-.*/\1/') | |
| if [ -f "$dir/test-results/android-results.json" ]; then | |
| # Check test status from results | |
| status=$(jq -r '.results["bcd-collection"].status // "unknown"' "$dir/test-results/android-results.json") | |
| device=$(jq -r '.deviceModel // "unknown"' "$dir/test-results/android-results.json") | |
| webview=$(jq -r '.webviewVersion // "unknown"' "$dir/test-results/android-results.json") | |
| if [ "$status" = "passed" ]; then | |
| echo "- ✅ **API Level $api** - $device - WebView $webview" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- ❌ **API Level $api** - $device - Test $status" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # Show BCD data count | |
| bcdCount=$(jq -r '.results["bcd-collection"].data.bcdCount // 0' "$dir/test-results/android-results.json") | |
| echo " - Collected $bcdCount BCD features" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- ❌ **API Level $api** - No results file generated" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| fi | |
| done | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "## iOS Results" >> $GITHUB_STEP_SUMMARY | |
| for dir in all-results/ios-*; do | |
| if [ -d "$dir" ]; then | |
| version=$(basename "$dir" | sed 's/ios-\([0-9.]*\)-.*/\1/') | |
| if [ -f "$dir/test-results/ios-results.json" ]; then | |
| # Check test status from results | |
| status=$(jq -r '.results["bcd-collection"].status // "unknown"' "$dir/test-results/ios-results.json") | |
| device=$(jq -r '.deviceModel // "unknown"' "$dir/test-results/ios-results.json") | |
| webview=$(jq -r '.webviewVersion // "unknown"' "$dir/test-results/ios-results.json") | |
| if [ "$status" = "passed" ]; then | |
| echo "- ✅ **iOS $version** - $device - $webview" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- ❌ **iOS $version** - $device - Test $status" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # Show BCD data count | |
| bcdCount=$(jq -r '.results["bcd-collection"].data.bcdCount // 0' "$dir/test-results/ios-results.json") | |
| echo " - Collected $bcdCount BCD features" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- ❌ **iOS $version** - No results file generated" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| fi | |
| done | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "---" >> $GITHUB_STEP_SUMMARY | |
| # Check if uploads were attempted | |
| if [ "${{ github.event_name }}" = "schedule" ] || [ "${{ inputs.upload_results }}" = "true" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 📤 Upload Status" >> $GITHUB_STEP_SUMMARY | |
| # Count successful uploads | |
| uploaded=0 | |
| for dir in all-results/*/; do | |
| if [ -f "$dir/test-results/*-results.json" ]; then | |
| uploaded=$((uploaded + 1)) | |
| fi | |
| done | |
| if [ $uploaded -gt 0 ]; then | |
| echo "✅ Results uploaded to [webview-bcd-results](https://github.com/WebView-CG/webview-bcd-results)" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "⚠️ No results were uploaded (files may not have been generated)" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| else | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "ℹ️ Results upload skipped (manual run without upload flag)" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "📊 **View all results**: [webview-bcd-results](https://github.com/WebView-CG/webview-bcd-results)" >> $GITHUB_STEP_SUMMARY |