significant android work
This commit is contained in:
379
.github/workflows/firebase-test-lab.yml
vendored
Normal file
379
.github/workflows/firebase-test-lab.yml
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
name: Firebase Test Lab
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'android/**'
|
||||
- '.github/workflows/firebase-test-lab.yml'
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'android/**'
|
||||
- '.github/workflows/firebase-test-lab.yml'
|
||||
# Allow manual trigger for release verification
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_type:
|
||||
description: 'Build type to test'
|
||||
required: true
|
||||
default: 'release'
|
||||
type: choice
|
||||
options:
|
||||
- release
|
||||
- debug
|
||||
skip_robo:
|
||||
description: 'Skip Robo tests'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_instrumentation:
|
||||
description: 'Skip instrumentation tests'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# ============================================================================
|
||||
# Build Job: Compile the Android app and test APK
|
||||
# ============================================================================
|
||||
build:
|
||||
name: Build APKs
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
gradle-version: wrapper
|
||||
|
||||
- name: Cache Gradle dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
android/.gradle
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle.kts', 'android/gradle/libs.versions.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
- name: Build release APK
|
||||
run: |
|
||||
cd android
|
||||
./gradlew :app:assembleProdRelease :app:assembleProdDebugAndroidTest --no-daemon
|
||||
|
||||
- name: Upload app APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: app-release-apk
|
||||
path: android/app/build/outputs/apk/prod/release/*.apk
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload test APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: app-test-apk
|
||||
path: android/app/build/outputs/apk/androidTest/prod/debug/*.apk
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload AAB (for Robo tests)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: app-release-aab
|
||||
path: android/app/build/outputs/bundle/prodRelease/*.aab
|
||||
retention-days: 7
|
||||
|
||||
# ============================================================================
|
||||
# Robo Tests Job: Crash/ANR detection via autonomous crawl
|
||||
# ============================================================================
|
||||
robo-tests:
|
||||
name: Robo Tests
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Authenticate to Google Cloud
|
||||
uses: google-github-actions/auth@v2
|
||||
with:
|
||||
credentials_json: ${{ secrets.GCP_SA_KEY_TEST_LAB }}
|
||||
|
||||
- name: Set up Cloud SDK
|
||||
uses: google-github-actions/setup-gcloud@v2
|
||||
with:
|
||||
project_id: ${{ secrets.FIREBASE_PROJECT_ID || 'kordant-android' }}
|
||||
|
||||
- name: Download AAB
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: app-release-aab
|
||||
path: build/
|
||||
- name: Download APK (fallback)
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: app-release-apk
|
||||
path: build/
|
||||
|
||||
- name: Run Robo tests
|
||||
id: robo
|
||||
run: |
|
||||
# Check which file type is available (prefer AAB)
|
||||
AAB_FILE=$(find build -name "*.aab" -type f 2>/dev/null | head -1)
|
||||
APK_FILE=$(find build -name "*prod-release.apk" -type f 2>/dev/null | head -1)
|
||||
|
||||
SCRIPT_DIR="android/firebase-test-lab"
|
||||
|
||||
if [ -n "$AAB_FILE" ]; then
|
||||
echo "Using AAB: $AAB_FILE"
|
||||
gcloud firebase test android run \
|
||||
--type robo \
|
||||
--project "${{ secrets.FIREBASE_PROJECT_ID || 'kordant-android' }}" \
|
||||
--app-package "com.kordant.android" \
|
||||
--aab "$AAB_FILE" \
|
||||
--robo-script "$SCRIPT_DIR/robo_script.json" \
|
||||
--device model=Pixel6,version=33,locale=en_US,orientation=portrait \
|
||||
--device model=Pixel6,version=33,locale=en_US,orientation=landscape \
|
||||
--device model=Pixel6,version=33,locale=es_ES,orientation=portrait \
|
||||
--device model=Pixel6,version=33,locale=es_ES,orientation=landscape \
|
||||
--device model=Pixel4,version=30,locale=en_US,orientation=portrait \
|
||||
--device model=Pixel4,version=30,locale=en_US,orientation=landscape \
|
||||
--device model=Pixel4,version=30,locale=es_ES,orientation=portrait \
|
||||
--device model=Pixel4,version=30,locale=es_ES,orientation=landscape \
|
||||
--device model=GalaxyS21,version=31,locale=en_US,orientation=portrait \
|
||||
--device model=GalaxyS21,version=31,locale=en_US,orientation=landscape \
|
||||
--device model=GalaxyS21,version=31,locale=es_ES,orientation=portrait \
|
||||
--device model=GalaxyS21,version=31,locale=es_ES,orientation=landscape \
|
||||
--device model=RedmiNote8,version=29,locale=en_US,orientation=portrait \
|
||||
--device model=RedmiNote8,version=29,locale=en_US,orientation=landscape \
|
||||
--device model=RedmiNote8,version=29,locale=es_ES,orientation=portrait \
|
||||
--device model=RedmiNote8,version=29,locale=es_ES,orientation=landscape \
|
||||
--device model=AquestM2,version=28,locale=en_US,orientation=portrait \
|
||||
--device model=AquestM2,version=28,locale=en_US,orientation=landscape \
|
||||
--device model=AquestM2,version=28,locale=es_ES,orientation=portrait \
|
||||
--device model=AquestM2,version=28,locale=es_ES,orientation=landscape \
|
||||
--timeout 60m \
|
||||
--max-crawl-time 600 \
|
||||
--record-video \
|
||||
--performance-metrics \
|
||||
--results-history-name "Kordant Android Robo CI" \
|
||||
--fail-fast \
|
||||
|| ROBO_EXIT=$?
|
||||
elif [ -n "$APK_FILE" ]; then
|
||||
echo "Using APK: $APK_FILE"
|
||||
gcloud firebase test android run \
|
||||
--type robo \
|
||||
--project "${{ secrets.FIREBASE_PROJECT_ID || 'kordant-android' }}" \
|
||||
--app "$APK_FILE" \
|
||||
--robo-script "$SCRIPT_DIR/robo_script.json" \
|
||||
--device model=Pixel6,version=33,locale=en_US,orientation=portrait \
|
||||
--device model=Pixel6,version=33,locale=en_US,orientation=landscape \
|
||||
--device model=Pixel6,version=33,locale=es_ES,orientation=portrait \
|
||||
--device model=Pixel6,version=33,locale=es_ES,orientation=landscape \
|
||||
--device model=Pixel4,version=30,locale=en_US,orientation=portrait \
|
||||
--device model=Pixel4,version=30,locale=en_US,orientation=landscape \
|
||||
--device model=Pixel4,version=30,locale=es_ES,orientation=portrait \
|
||||
--device model=Pixel4,version=30,locale=es_ES,orientation=landscape \
|
||||
--device model=GalaxyS21,version=31,locale=en_US,orientation=portrait \
|
||||
--device model=GalaxyS21,version=31,locale=en_US,orientation=landscape \
|
||||
--device model=GalaxyS21,version=31,locale=es_ES,orientation=portrait \
|
||||
--device model=GalaxyS21,version=31,locale=es_ES,orientation=landscape \
|
||||
--device model=RedmiNote8,version=29,locale=en_US,orientation=portrait \
|
||||
--device model=RedmiNote8,version=29,locale=en_US,orientation=landscape \
|
||||
--device model=RedmiNote8,version=29,locale=es_ES,orientation=portrait \
|
||||
--device model=RedmiNote8,version=29,locale=es_ES,orientation=landscape \
|
||||
--device model=AquestM2,version=28,locale=en_US,orientation=portrait \
|
||||
--device model=AquestM2,version=28,locale=en_US,orientation=landscape \
|
||||
--device model=AquestM2,version=28,locale=es_ES,orientation=portrait \
|
||||
--device model=AquestM2,version=28,locale=es_ES,orientation=landscape \
|
||||
--timeout 60m \
|
||||
--max-crawl-time 600 \
|
||||
--record-video \
|
||||
--performance-metrics \
|
||||
--results-history-name "Kordant Android Robo CI" \
|
||||
--fail-fast \
|
||||
|| ROBO_EXIT=$?
|
||||
else
|
||||
echo "No APK or AAB found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "ROBO_EXIT_CODE=${ROBO_EXIT:-0}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload Robo test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: robo-test-results
|
||||
path: |
|
||||
android/firebase-test-lab/robo_script.json
|
||||
build/*.aab
|
||||
build/*prod-release*.apk
|
||||
retention-days: 14
|
||||
|
||||
- name: Mark build as failed if Robo tests failed
|
||||
if: steps.robo.outputs.ROBO_EXIT_CODE != '0'
|
||||
run: |
|
||||
echo "❌ Robo tests failed with exit code ${{ steps.robo.outputs.ROBO_EXIT_CODE }}"
|
||||
echo "Review results in Firebase Console"
|
||||
exit 1
|
||||
|
||||
# ============================================================================
|
||||
# Instrumentation Tests Job: UI tests with assertions
|
||||
# ============================================================================
|
||||
instrumentation-tests:
|
||||
name: Instrumentation Tests
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Authenticate to Google Cloud
|
||||
uses: google-github-actions/auth@v2
|
||||
with:
|
||||
credentials_json: ${{ secrets.GCP_SA_KEY_TEST_LAB }}
|
||||
|
||||
- name: Set up Cloud SDK
|
||||
uses: google-github-actions/setup-gcloud@v2
|
||||
with:
|
||||
project_id: ${{ secrets.FIREBASE_PROJECT_ID || 'kordant-android' }}
|
||||
|
||||
- name: Download APKs
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: app-release-apk
|
||||
path: build/apk/
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: app-test-apk
|
||||
path: build/apk/
|
||||
|
||||
- name: Run Instrumentation tests
|
||||
id: instrumentation
|
||||
run: |
|
||||
APP_APK=$(find build/apk -name "*prod-release.apk" -type f 2>/dev/null | head -1)
|
||||
TEST_APK=$(find build/apk -name "*androidTest*.apk" -type f 2>/dev/null | head -1)
|
||||
|
||||
if [ -z "$APP_APK" ] || [ -z "$TEST_APK" ]; then
|
||||
echo "Error: Could not find APK files."
|
||||
echo "App APK: ${APP_APK:-not found}"
|
||||
echo "Test APK: ${TEST_APK:-not found}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "App APK: $APP_APK"
|
||||
echo "Test APK: $TEST_APK"
|
||||
|
||||
gcloud firebase test android run \
|
||||
--type instrumentation \
|
||||
--project "${{ secrets.FIREBASE_PROJECT_ID || 'kordant-android' }}" \
|
||||
--app "$APP_APK" \
|
||||
--test "$TEST_APK" \
|
||||
--device model=Pixel6,version=33,locale=en_US,orientation=portrait \
|
||||
--device model=Pixel6,version=33,locale=en_US,orientation=landscape \
|
||||
--device model=Pixel6,version=33,locale=es_ES,orientation=portrait \
|
||||
--device model=Pixel6,version=33,locale=es_ES,orientation=landscape \
|
||||
--device model=Pixel4,version=30,locale=en_US,orientation=portrait \
|
||||
--device model=Pixel4,version=30,locale=en_US,orientation=landscape \
|
||||
--device model=Pixel4,version=30,locale=es_ES,orientation=portrait \
|
||||
--device model=Pixel4,version=30,locale=es_ES,orientation=landscape \
|
||||
--device model=GalaxyS21,version=31,locale=en_US,orientation=portrait \
|
||||
--device model=GalaxyS21,version=31,locale=en_US,orientation=landscape \
|
||||
--device model=GalaxyS21,version=31,locale=es_ES,orientation=portrait \
|
||||
--device model=GalaxyS21,version=31,locale=es_ES,orientation=landscape \
|
||||
--device model=RedmiNote8,version=29,locale=en_US,orientation=portrait \
|
||||
--device model=RedmiNote8,version=29,locale=en_US,orientation=landscape \
|
||||
--device model=RedmiNote8,version=29,locale=es_ES,orientation=portrait \
|
||||
--device model=RedmiNote8,version=29,locale=es_ES,orientation=landscape \
|
||||
--device model=AquestM2,version=28,locale=en_US,orientation=portrait \
|
||||
--device model=AquestM2,version=28,locale=en_US,orientation=landscape \
|
||||
--device model=AquestM2,version=28,locale=es_ES,orientation=portrait \
|
||||
--device model=AquestM2,version=28,locale=es_ES,orientation=landscape \
|
||||
--timeout 60m \
|
||||
--num-flaky-test-attempts 2 \
|
||||
--record-video \
|
||||
--performance-metrics \
|
||||
--results-history-name "Kordant Android Instrumentation CI" \
|
||||
--fail-fast \
|
||||
|| INSTR_EXIT=$?
|
||||
|
||||
echo "INSTR_EXIT_CODE=${INSTR_EXIT:-0}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload instrumentation test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: instrumentation-test-results
|
||||
path: build/apk/
|
||||
retention-days: 14
|
||||
|
||||
- name: Mark build as failed if instrumentation tests failed
|
||||
if: steps.instrumentation.outputs.INSTR_EXIT_CODE != '0'
|
||||
run: |
|
||||
echo "❌ Instrumentation tests failed with exit code ${{ steps.instrumentation.outputs.INSTR_EXIT_CODE }}"
|
||||
echo "Review results in Firebase Console"
|
||||
exit 1
|
||||
|
||||
# ============================================================================
|
||||
# Summary Job: Collect all test results
|
||||
# ============================================================================
|
||||
test-summary:
|
||||
name: Test Summary
|
||||
needs: [robo-tests, instrumentation-tests]
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check test results
|
||||
run: |
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "📊 Firebase Test Lab - CI Results Summary"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "View detailed results in Firebase Console:"
|
||||
echo " https://console.firebase.google.com/project/${{ secrets.FIREBASE_PROJECT_ID || 'kordant-android' }}/testlab"
|
||||
echo ""
|
||||
echo "Devices tested:"
|
||||
echo " ✅ Pixel 6 (API 33) - primary target"
|
||||
echo " ✅ Pixel 4 (API 30) - older device"
|
||||
echo " ✅ Galaxy S21 (API 31) - Samsung"
|
||||
echo " ✅ Redmi Note 8 (API 29) - Xiaomi"
|
||||
echo " ✅ Aquest M2 (API 28) - low-end device"
|
||||
echo ""
|
||||
echo "Orientations: portrait, landscape"
|
||||
echo "Locales: en_US, es_ES"
|
||||
echo ""
|
||||
|
||||
- name: Send notification on failure
|
||||
if: failure()
|
||||
run: |
|
||||
echo "::warning::Firebase Test Lab tests failed. Check the Firebase Console for details."
|
||||
|
||||
- name: Determine overall status
|
||||
run: |
|
||||
if [ "${{ needs.robo-tests.result }}" = "failure" ] || [ "${{ needs.instrumentation-tests.result }}" = "failure" ]; then
|
||||
echo "❌ Firebase Test Lab: FAILED"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ Firebase Test Lab: PASSED"
|
||||
fi
|
||||
Reference in New Issue
Block a user