Fix Node.js version compatibility for @solana/codecs-numbers dependency #5
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: 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 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 production APK..." | |
| 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 | |
| echo "Production APK built successfully" | |
| else | |
| echo "No production keystore found, skipping production build" | |
| fi | |
| - name: Sign Production APK (if available) | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| working-directory: ./android | |
| run: | | |
| if [ -f "release.keystore" ] && [ -f "app/build/outputs/apk/release/app-release-unsigned.apk" ]; then | |
| echo "Signing production APK..." | |
| jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \ | |
| -keystore release.keystore \ | |
| -storepass "${{ secrets.ANDROID_KEYSTORE_PASSWORD }}" \ | |
| -keypass "${{ secrets.ANDROID_KEY_PASSWORD }}" \ | |
| app/build/outputs/apk/release/app-release-unsigned.apk \ | |
| "${{ secrets.ANDROID_KEY_ALIAS }}" | |
| # Verify the signature | |
| jarsigner -verify -verbose -certs app/build/outputs/apk/release/app-release-unsigned.apk | |
| # Rename to signed APK | |
| mv app/build/outputs/apk/release/app-release-unsigned.apk app/build/outputs/apk/release/app-release.apk | |
| echo "Production APK signed successfully" | |
| else | |
| echo "No production APK or keystore found, skipping signing" | |
| fi | |
| env: | |
| ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} | |
| ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} | |
| ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} | |
| - name: Sign APK (Debug) | |
| working-directory: ./android | |
| run: | | |
| # Generate debug keystore if it doesn't exist | |
| if [ ! -f "debug.keystore" ]; then | |
| keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US" | |
| fi | |
| # Sign the APK | |
| jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore debug.keystore -storepass android -keypass android app/build/outputs/apk/debug/app-debug.apk androiddebugkey | |
| - name: Verify APK | |
| working-directory: ./android | |
| run: | | |
| jarsigner -verify -verbose -certs app/build/outputs/apk/debug/app-debug.apk | |
| - 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 |