From d951fceaca0e5c3692dee5f7c65665ae513b3b1f Mon Sep 17 00:00:00 2001 From: Tony Giorgio Date: Tue, 18 Jul 2023 21:48:26 -0500 Subject: [PATCH] Add android build CI --- .github/workflows/android-build.yml | 85 ++++++++++++++ .github/workflows/android-prod.yml | 161 ++++++++++++++++++++++++++ .github/workflows/android-staging.yml | 161 ++++++++++++++++++++++++++ README.md | 42 +++++++ android/app/build.gradle | 13 ++- 5 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/android-build.yml create mode 100644 .github/workflows/android-prod.yml create mode 100644 .github/workflows/android-staging.yml diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml new file mode 100644 index 0000000..c815237 --- /dev/null +++ b/.github/workflows/android-build.yml @@ -0,0 +1,85 @@ +name: Build Android + +on: + push: + branches: + - master + - prod + pull_request: + branches: + - '*' + +jobs: + build: + name: Build APK + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v3 + + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '17' + + - name: Cache gradle + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - uses: pnpm/action-setup@v2 + name: Install pnpm + id: pnpm-install + with: + run_install: false + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install app dependencies + run: pnpm install + + - name: Build SolidJS app + env: + VITE_NETWORK: signet + VITE_PROXY: wss://p.mutinywallet.com + VITE_ESPLORA: https://mutinynet.com/api + VITE_LSP: https://signet-lsp.mutinywallet.com + VITE_RGS: https://rgs.mutinynet.com/snapshot/ + VITE_AUTH: https://auth-staging.mutinywallet.com + VITE_SUBSCRIPTIONS: https://subscriptions-staging.mutinywallet.com + VITE_STORAGE: https://storage-staging.mutinywallet.com + run: pnpm build + + - name: Capacitor sync + run: npx cap sync + + - name: Build APK (gradle) + working-directory: android + run: ./gradlew assembleDebug --no-daemon + + - name: Upload APK + uses: actions/upload-artifact@v2 + with: + name: Debug APK + path: android/app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk diff --git a/.github/workflows/android-prod.yml b/.github/workflows/android-prod.yml new file mode 100644 index 0000000..878bb3e --- /dev/null +++ b/.github/workflows/android-prod.yml @@ -0,0 +1,161 @@ +name: Build Android + +on: + push: + tags: + - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 + +jobs: + build: + name: Build APK + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v3 + + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '17' + + - name: Cache gradle + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - uses: pnpm/action-setup@v2 + name: Install pnpm + id: pnpm-install + with: + run_install: false + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install app dependencies + run: pnpm install + + - name: Build SolidJS app + env: + VITE_NETWORK: bitcoin + VITE_PROXY: wss://p.mutinywallet.com + VITE_ESPLORA: https://mempool.space/api + VITE_LSP: https://lsp.voltageapi.com + VITE_RGS: https://rapidsync.lightningdevkit.org/snapshot/ + VITE_AUTH: https://auth.mutinywallet.com + VITE_SUBSCRIPTIONS: https://subscriptions.mutinywallet.com + VITE_STORAGE: https://storage.mutinywallet.com + run: pnpm build + + - name: Capacitor sync + run: npx cap sync + + - name: Build AAB + working-directory: android + run: ./gradlew clean bundleRelease --stacktrace + + - name: Sign AAB (F-Droid) + uses: r0adkll/sign-android-release@v1 + working-directory: android + with: + releaseDirectory: app/build/outputs/bundle/fdroidRelease + signingKeyBase64: ${{ secrets.SIGNING_KEY }} + alias: ${{ secrets.KEY_ALIAS }} + keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} + keyPassword: ${{ secrets.KEY_PASSWORD }} + + - name: Build APK + working-directory: android + run: ./gradlew assembleRelease --stacktrace + + - name: Sign APK (F-Droid) + uses: r0adkll/sign-android-release@v1 + working-directory: android + with: + releaseDirectory: app/build/outputs/apk/fdroid/release + signingKeyBase64: ${{ secrets.SIGNING_KEY }} + alias: ${{ secrets.KEY_ALIAS }} + keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} + keyPassword: ${{ secrets.KEY_PASSWORD }} + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + + # F-Droid APK + - name: Upload F-Droid APK Universal Asset + id: upload-release-asset-fdroid-universal-apk + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-universal-release-unsigned-signed.apk + asset_name: mutiny-wallet-fdroid-universal-${{ github.ref_name }}.apk + asset_content_type: application/zip + + - name: Upload F-Droid APK x86 Asset + id: upload-release-asset-fdroid-x86-apk + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-x86-release-unsigned-signed.apk + asset_name: mutiny-wallet-fdroid-x86-${{ github.ref_name }}.apk + asset_content_type: application/zip + + - name: Upload F-Droid APK x86_64 Asset + id: upload-release-asset-fdroid-x86-64-apk + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-x86_64-release-unsigned-signed.apk + asset_name: mutiny-wallet-fdroid-x86_64-${{ github.ref_name }}.apk + asset_content_type: application/zip + + # FDroid AAB + - name: Upload F-Droid AAB Asset + id: upload-release-asset-fdroid-aab + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/bundle/fdroidRelease/app-fdroid-release.aab + asset_name: mutiny-wallet-fdroid-${{ github.ref_name }}.aab + asset_content_type: application/zip diff --git a/.github/workflows/android-staging.yml b/.github/workflows/android-staging.yml new file mode 100644 index 0000000..1063176 --- /dev/null +++ b/.github/workflows/android-staging.yml @@ -0,0 +1,161 @@ +name: Build Android + +on: + push: + branches: + - master + +jobs: + build: + name: Build APK + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v3 + + - name: Setup java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '17' + + - name: Cache gradle + uses: actions/cache@v1 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.x + + - uses: pnpm/action-setup@v2 + name: Install pnpm + id: pnpm-install + with: + run_install: false + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install app dependencies + run: pnpm install + + - name: Build SolidJS app + env: + VITE_NETWORK: signet + VITE_PROXY: wss://p.mutinywallet.com + VITE_ESPLORA: https://mutinynet.com/api + VITE_LSP: https://signet-lsp.mutinywallet.com + VITE_RGS: https://rgs.mutinynet.com/snapshot/ + VITE_AUTH: https://auth-staging.mutinywallet.com + VITE_SUBSCRIPTIONS: https://subscriptions-staging.mutinywallet.com + VITE_STORAGE: https://storage-staging.mutinywallet.com + run: pnpm build + + - name: Capacitor sync + run: npx cap sync + + - name: Build AAB + working-directory: android + run: ./gradlew clean bundleRelease --stacktrace + + - name: Sign AAB (F-Droid) + uses: r0adkll/sign-android-release@v1 + working-directory: android + with: + releaseDirectory: app/build/outputs/bundle/fdroidRelease + signingKeyBase64: ${{ secrets.SIGNING_KEY }} + alias: ${{ secrets.KEY_ALIAS }} + keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} + keyPassword: ${{ secrets.KEY_PASSWORD }} + + - name: Build APK + working-directory: android + run: ./gradlew assembleRelease --stacktrace + + - name: Sign APK (F-Droid) + uses: r0adkll/sign-android-release@v1 + working-directory: android + with: + releaseDirectory: app/build/outputs/apk/fdroid/release + signingKeyBase64: ${{ secrets.SIGNING_KEY }} + alias: ${{ secrets.KEY_ALIAS }} + keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} + keyPassword: ${{ secrets.KEY_PASSWORD }} + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.sha }} + release_name: Prerelease ${{ github.sha }} + draft: false + prerelease: true # only prerelease for normal builds + + # F-Droid APK + - name: Upload F-Droid APK Universal Asset + id: upload-release-asset-fdroid-universal-apk + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-universal-release-unsigned-signed.apk + asset_name: mutiny-wallet-fdroid-universal-master.apk + asset_content_type: application/zip + + - name: Upload F-Droid APK x86 Asset + id: upload-release-asset-fdroid-x86-apk + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-x86-release-unsigned-signed.apk + asset_name: mutiny-wallet-fdroid-x86-master.apk + asset_content_type: application/zip + + - name: Upload F-Droid APK x86_64 Asset + id: upload-release-asset-fdroid-x86-64-apk + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-x86_64-release-unsigned-signed.apk + asset_name: mutiny-wallet-fdroid-x86_64-master.apk + asset_content_type: application/zip + + # FDroid AAB + - name: Upload F-Droid AAB Asset + id: upload-release-asset-fdroid-aab + uses: actions/upload-release-asset@v1 + working-directory: android + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/bundle/fdroidRelease/app-fdroid-release.aab + asset_name: mutiny-wallet-fdroid-master.aab + asset_content_type: application/zip diff --git a/README.md b/README.md index 8a83a8f..9dae6a2 100644 --- a/README.md +++ b/README.md @@ -56,3 +56,45 @@ To revert back and use the remote version of mutiny-wasm: ``` just remote ``` + +## Android + +### How to test locally + +``` +pnpm build && npx cap sync +``` + +Now open up the `android` directory in android studio and run the build + +### Deploying + +#### Pull Requests + +Each pull request will build the debug signet app and upload it internally to the github actions run. + +#### Master + +Each push to master will build a signed release version running in signet mode. The build process is almost identical to the release version. + +Prereleased tags will be created for master. + +#### Release + +First bump up the `versionCode` and `versionName` in `./andriod/app/build.gradle`. The `versionCode` must always go up by one when making a release. The `versionName` can mimic `package.json` with an extra build number like `0.4.3-1` to make it easier to keep things looking like they are in sync when android only releases go out. + +Publish a new tag like `0.4.3-1` in order to trigger a signed release version running in mainnet mode. + +### Creating keys for the first time + +1. Generate a new signing key +``` +keytool -genkey -v -keystore -alias -keyalg RSA -keysize 2048 -validity 10000 +openssl base64 < | tr -d '\n' | tee some_signing_key.jks.base64.txt +``` +2. Create 3 Secret Key variables on your GitHub repository and fill in with the signing key information + - `KEY_ALIAS` <- `` + - `KEY_STORE_PASSWORD` <- `` + - `SIGNING_KEY` <- the data from `` +3. Change the `versionCode` and `versionName` on `app/build.gradle` +4. Commit and push. diff --git a/android/app/build.gradle b/android/app/build.gradle index 22109ca..e3c5ada 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -8,7 +8,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 - versionName "1.0" + versionName "0.4.3-1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. @@ -22,6 +22,17 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + flavorDimensions "channel" + productFlavors { + play { + dimension "channel" + } + + fdroid { + getIsDefault().set(true) + dimension "channel" + } + } } repositories {