diff --git a/.github/workflows/android_e2e.yml b/.github/workflows/android_e2e.yml new file mode 100644 index 0000000000..e0fb6dfb05 --- /dev/null +++ b/.github/workflows/android_e2e.yml @@ -0,0 +1,174 @@ +name: Android E2E + +on: + pull_request: + +env: + TZ: "Asia/Tokyo" + +# 並列実行の制御 +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + e2e: + runs-on: ubuntu-latest + timeout-minutes: 45 # タイムアウト設定 + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + ssh-key: ${{ secrets.FONTS_SSH_KEY }} + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "pnpm" + + - uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: "17" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Restore .env.local + shell: bash + run: echo "$DOTENV_LOCAL" | tr -d '\r' > ./.env.local + env: + DOTENV_LOCAL: ${{ secrets.DOTENV_LOCAL }} + + - name: Restore google-services.json + shell: bash + run: echo "$GOOGLE_SERVICES_JSON" | tr -d '\r' > ./android/app/src/dev/google-services.json + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} + + - name: Restore play-store-credentials.json + shell: bash + run: echo "$PLAY_STORE_CREDENTIALS_JSON" | tr -d '\r' > ./android/play-store-credentials.json + env: + PLAY_STORE_CREDENTIALS_JSON: ${{ secrets.PLAY_STORE_CREDENTIALS_JSON }} + + - name: Restore release.keystore + shell: bash + run: echo "${{ secrets.RELEASE_KEYSTORE }}" | base64 --decode > ./android/app/release.keystore + env: + RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }} + + - name: Restore sentry.properties + shell: bash + run: echo "${{ secrets.SENTRY_PROPERTIES_BASE64 }}" | base64 --decode > ./android/sentry.properties + env: + SENTRY_PROPERTIES_BASE64: ${{ secrets.SENTRY_PROPERTIES_BASE64 }} + + - name: Install maestro + run: | + curl -fsSL "https://get.maestro.mobile.dev" | bash + echo "$HOME/.maestro/bin" >> $GITHUB_PATH + + - name: Update cmdline-tools + run: | + mkdir -p "$ANDROID_SDK_ROOT/cmdline-tools" + cd "$ANDROID_SDK_ROOT/cmdline-tools" + curl -O https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip + unzip -q commandlinetools-linux-*.zip -d temp + mv temp "$ANDROID_SDK_ROOT/cmdline-tools/latest" + rm commandlinetools-linux-*.zip + echo "$ANDROID_SDK_ROOT/emulator" >> $GITHUB_PATH + echo "$ANDROID_SDK_ROOT/platform-tools" >> $GITHUB_PATH + echo "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin" >> $GITHUB_PATH + - name: Run Android E2E (Metro + AVD + Maestro) + shell: bash + run: | + echo "🧱 Creating AVD..." + mkdir -p "$HOME/.android/avd" + sdkmanager --licenses < /dev/null + sdkmanager "system-images;android-30;google_apis;x86_64" + echo "no" | avdmanager create avd \ + -n test \ + -k "system-images;android-30;google_apis;x86_64" \ + -d "Nexus 5" + if [ ! -f "$HOME/.android/avd/test.avd/config.ini" ]; then + echo "❌ Failed to create AVD" + ls -l "$HOME/.android/avd" + exit 1 + fi + echo "🚀 Starting emulator..." + emulator -avd test -no-snapshot -no-window -gpu swiftshader_indirect -no-audio & + EMULATOR_PID=$! + + echo "⏳ Waiting for emulator boot..." + booted=0 + for i in {1..60}; do + if adb shell getprop sys.boot_completed | grep 1 > /dev/null; then + echo "✅ Emulator booted" + booted=1 + break + fi + echo "Waiting for boot... ($i/60)" + sleep 5 + done + + if [ "$booted" -eq 0 ]; then + echo "❌ Emulator failed to boot within 300 seconds" + adb logcat -d > emulator_logcat.txt + exit 1 + fi + + echo "🌐 Starting Metro..." + pnpm start --reset-cache & + METRO_PID=$! + + echo "📦 Installing app..." + pnpm run android -- --variant devRelease + + echo "🧪 Running Maestro tests..." + $HOME/.maestro/bin/maestro test Flow.yaml + + echo "🧹 Cleaning up..." + kill $METRO_PID || true + kill $EMULATOR_PID || true + - name: Upload Metro logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: metro-logs-${{ github.run_number }} + path: metro.log + + - name: Upload Maestro screenshots + if: always() + uses: actions/upload-artifact@v4 + with: + name: maestro-screenshots-${{ github.run_number }} + path: maestro-screenshots/ + retention-days: 30 + + - name: Upload Maestro test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: maestro-test-results-${{ github.run_number }} + path: maestro-results.xml + retention-days: 30 + + - name: Cleanup + if: always() + run: | + # Metro Bundlerのクリーンアップ + pkill -f "pnpm start" || true + pkill -f "metro" || true + + # エミュレーター関連プロセスのクリーンアップ + pkill -f "emulator" || true + pkill -f "qemu" || true + + # adbプロセスのクリーンアップ + adb kill-server 2>/dev/null || true \ No newline at end of file