Skip to content

Fix Android build workflow: reorder Gradle caching and fix compilatio… #3

Fix Android build workflow: reorder Gradle caching and fix compilatio…

Fix Android build workflow: reorder Gradle caching and fix compilatio… #3

Workflow file for this run

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: '18.20.0'
cache: 'yarn'
- name: Setup Java JDK
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
api-level: 34
build-tools: 34.0.0
- 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: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
android/.gradle
android/app/.gradle
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/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