Fix black screen issue by migrating makeStyles to modern MUI patterns #10
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: Build Android APK | |
| on: | |
| push: | |
| branches: [ main, develop, 'feature/*', 'fix/*', 'copilot/*' ] | |
| paths-ignore: | |
| - 'docs/**' | |
| - '*.md' | |
| pull_request: | |
| branches: [ main, develop ] | |
| paths-ignore: | |
| - 'docs/**' | |
| - '*.md' | |
| workflow_dispatch: | |
| jobs: | |
| build-android: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20.x' | |
| cache: 'yarn' | |
| - name: Cache Node modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| node_modules | |
| ~/.yarn/cache | |
| key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-yarn- | |
| - name: Install dependencies | |
| run: yarn install --frozen-lockfile | |
| - name: Build web application | |
| run: yarn build | |
| - name: Initialize Capacitor (if not exists) | |
| run: | | |
| if [ ! -d "android" ] && [ ! -f "capacitor.config.ts" ]; then | |
| npx cap init "SVMSeek Wallet" "com.svmseek.wallet" --web-dir=build | |
| fi | |
| - name: Add Android platform (if not exists) | |
| run: | | |
| if [ ! -d "android" ]; then | |
| npx cap add android | |
| fi | |
| - name: Setup Java JDK | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| - name: Setup Android SDK | |
| uses: android-actions/setup-android@v3 | |
| with: | |
| api-level: 34 | |
| build-tools: 34.0.0 | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v4 | |
| if: hashFiles('android/**/*.gradle*', 'android/**/gradle-wrapper.properties') != '' | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| android/.gradle | |
| android/app/.gradle | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle*', 'android/**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-gradle- | |
| - name: Sync Capacitor | |
| run: npx cap sync android | |
| - name: Grant execute permission for gradlew | |
| run: chmod +x android/gradlew | |
| - name: Clean Android project | |
| working-directory: ./android | |
| run: | | |
| # Clean project to remove any corrupted resources or build artifacts | |
| ./gradlew clean --stacktrace | |
| - name: Build Android APK | |
| working-directory: ./android | |
| run: | | |
| # Configure Gradle for faster builds | |
| export GRADLE_OPTS="-Dorg.gradle.jvmargs=-Xmx4096m -Dorg.gradle.parallel=true -Dorg.gradle.configureondemand=true -Dorg.gradle.daemon=true -Dorg.gradle.caching=true" | |
| ./gradlew assembleDebug --stacktrace --build-cache --parallel --configure-on-demand | |
| - name: Setup Production Keystore (if secrets available) | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| working-directory: ./android | |
| run: | | |
| if [ ! -z "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" ]; then | |
| echo "Setting up production keystore..." | |
| echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > release.keystore | |
| echo "Production keystore created" | |
| else | |
| echo "No production keystore secrets found, skipping production build" | |
| fi | |
| env: | |
| ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | |
| - name: Build and Sign Production APK (if production keystore available) | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| working-directory: ./android | |
| run: | | |
| if [ -f "release.keystore" ]; then | |
| echo "Building and signing production APK..." | |
| # Clean before production build to prevent resource corruption | |
| ./gradlew clean --stacktrace | |
| # Configure signing in gradle.properties for production build | |
| echo "MYAPP_UPLOAD_STORE_FILE=../release.keystore" >> gradle.properties | |
| echo "MYAPP_UPLOAD_KEY_ALIAS=${{ secrets.ANDROID_KEY_ALIAS }}" >> gradle.properties | |
| echo "MYAPP_UPLOAD_STORE_PASSWORD=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}" >> gradle.properties | |
| echo "MYAPP_UPLOAD_KEY_PASSWORD=${{ secrets.ANDROID_KEY_PASSWORD }}" >> gradle.properties | |
| # Build signed release APK directly (Gradle handles signing automatically) | |
| export GRADLE_OPTS="-Dorg.gradle.jvmargs=-Xmx4096m -Dorg.gradle.parallel=true -Dorg.gradle.configureondemand=true -Dorg.gradle.daemon=true -Dorg.gradle.caching=true" | |
| ./gradlew assembleRelease --stacktrace --build-cache --parallel --configure-on-demand | |
| # Verify the signed APK exists and is valid | |
| if [ -f "app/build/outputs/apk/release/app-release.apk" ]; then | |
| echo "Production APK built and signed successfully" | |
| # Basic APK validation | |
| unzip -l app/build/outputs/apk/release/app-release.apk | grep "META-INF.*\.RSA\|META-INF.*\.DSA" && echo "APK is properly signed" || echo "Warning: APK signing verification incomplete" | |
| else | |
| echo "Production APK not found after build" | |
| ls -la app/build/outputs/apk/release/ || echo "Release output directory not found" | |
| exit 1 | |
| fi | |
| else | |
| echo "No production keystore found, skipping production build" | |
| fi | |
| env: | |
| ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} | |
| ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} | |
| ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} | |
| - name: Verify APKs | |
| working-directory: ./android | |
| run: | | |
| echo "Verifying debug APK..." | |
| if [ -f "app/build/outputs/apk/debug/app-debug.apk" ]; then | |
| # Basic APK structure validation | |
| unzip -l app/build/outputs/apk/debug/app-debug.apk > /dev/null && echo "Debug APK structure is valid" | |
| echo "Debug APK verified successfully" | |
| else | |
| echo "Debug APK not found for verification" | |
| ls -la app/build/outputs/apk/debug/ || echo "Debug output directory not found" | |
| exit 1 | |
| fi | |
| # Verify production APK if it exists | |
| if [ -f "app/build/outputs/apk/release/app-release.apk" ]; then | |
| echo "Verifying production APK..." | |
| unzip -l app/build/outputs/apk/release/app-release.apk > /dev/null && echo "Production APK structure is valid" | |
| echo "Production APK verified successfully" | |
| fi | |
| - name: Rename APK with version | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| TIMESTAMP=$(date +%Y%m%d-%H%M%S) | |
| # Copy debug APK (always available) | |
| cp android/app/build/outputs/apk/debug/app-debug.apk svmseek-wallet-debug-v${VERSION}-${TIMESTAMP}.apk | |
| # Copy production APK if available | |
| if [ -f "android/app/build/outputs/apk/release/app-release.apk" ]; then | |
| cp android/app/build/outputs/apk/release/app-release.apk svmseek-wallet-production-v${VERSION}-${TIMESTAMP}.apk | |
| echo "Production APK renamed: svmseek-wallet-production-v${VERSION}-${TIMESTAMP}.apk" | |
| fi | |
| echo "Debug APK renamed: svmseek-wallet-debug-v${VERSION}-${TIMESTAMP}.apk" | |
| - name: Upload APK artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: svmseek-wallet-apk | |
| path: svmseek-wallet-*.apk | |
| retention-days: 30 | |
| - name: Upload Production APK as release asset (on main branch) | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: svmseek-wallet-production-apk | |
| path: svmseek-wallet-production-*.apk | |
| retention-days: 90 | |
| if-no-files-found: ignore |