From 94d2ba72f80fef1ce92981b8a2380262d5f113f0 Mon Sep 17 00:00:00 2001 From: CodeGhost21 <164498022+CodeGhost21@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:59:32 +0530 Subject: [PATCH] Add workflow to build and package Android APK (#28) * chore: bump version to 0.20.0 [skip ci] * chore: bump version to 0.21.0 [skip ci] * Add workflow to build and package Android APK * fix: fix package-android job issues in CI workflow - Add PR branch ref to checkout step for consistent behavior - Add missing frontend build step with VITE_* env vars before Android build - Split APK build into signed/unsigned steps to avoid signing with missing keystore - Add environment: Production for access to environment-scoped secrets/variables - Fix wrong auth token ($GH_TOKEN -> $XGH_TOKEN) in release asset upload Co-Authored-By: Claude Opus 4.5 * fix: fix package-android job issues in CI workflow - Add PR branch ref to checkout step for consistent behavior - Add missing frontend build step with VITE_* env vars before Android build - Split APK build into signed/unsigned steps to avoid signing with missing keystore - Add environment: Production for access to environment-scoped secrets/variables - Fix wrong auth token ($GH_TOKEN -> $XGH_TOKEN) in release asset upload Co-Authored-By: Claude Opus 4.5 --------- Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Claude Opus 4.5 --- .github/workflows/package-and-publish.yml | 123 +++++++++++++++++++++- package.json | 2 +- 2 files changed, 123 insertions(+), 2 deletions(-) diff --git a/.github/workflows/package-and-publish.yml b/.github/workflows/package-and-publish.yml index 046b18263..bb42e8063 100644 --- a/.github/workflows/package-and-publish.yml +++ b/.github/workflows/package-and-publish.yml @@ -388,9 +388,130 @@ jobs: name: ${{ steps.file-info.outputs.filename }} path: ${{ steps.file-info.outputs.path }}/${{ steps.file-info.outputs.filename }} + package-android: + name: Build and package Android APK + needs: [get-version, check-version, create-release] + if: ${{ !failure() && !cancelled() && needs.check-version.outputs.should-skip != 'true' }} + environment: Production + runs-on: ubuntu-22.04 + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref }} + + - name: Setup Node.js 24.x + uses: actions/setup-node@v4 + with: + node-version: 24.x + cache: 'yarn' + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android + + - name: Setup Java 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Install Android NDK + run: sdkmanager --install "ndk;27.0.12077973" + + - name: Set NDK path + run: echo "NDK_HOME=$ANDROID_HOME/ndk/27.0.12077973" >> $GITHUB_ENV + + - name: Cache node modules + id: yarn-cache + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-build-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-build- + + - name: Install dependencies + if: steps.yarn-cache.outputs.cache-hit != 'true' + run: yarn install --frozen-lockfile + + - name: Build frontend + run: yarn build + env: + NODE_ENV: production + VITE_BACKEND_URL: ${{ vars.VITE_BACKEND_URL }} + VITE_TELEGRAM_BOT_USERNAME: ${{ secrets.VITE_TELEGRAM_BOT_USERNAME }} + VITE_TELEGRAM_BOT_ID: ${{ secrets.VITE_TELEGRAM_BOT_ID }} + VITE_TELEGRAM_API_ID: ${{ secrets.VITE_TELEGRAM_API_ID }} + VITE_TELEGRAM_API_HASH: ${{ secrets.VITE_TELEGRAM_API_HASH }} + VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }} + VITE_SKILLS_GITHUB_REPO: ${{ vars.VITE_SKILLS_GITHUB_REPO }} + VITE_DEBUG: ${{ vars.VITE_DEBUG }} + + - name: Initialize Tauri Android + run: npx tauri android init + + - name: Decode keystore + if: needs.get-version.outputs.should-publish != '' + env: + ANDROID_KEYSTORE: ${{ secrets.ANDROID_KEYSTORE }} + run: | + echo "$ANDROID_KEYSTORE" | base64 --decode > ${{ github.workspace }}/release.jks + + - name: Build Android APK (signed) + if: needs.get-version.outputs.should-publish != '' + env: + BASE_URL: ${{ vars.BASE_URL }} + ANDROID_KEYSTORE_PATH: ${{ github.workspace }}/release.jks + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + run: npx tauri android build --apk + + - name: Build Android APK (unsigned) + if: needs.get-version.outputs.should-publish == '' + env: + BASE_URL: ${{ vars.BASE_URL }} + run: npx tauri android build --apk + + - name: Find APK + id: find-apk + run: | + APK_PATH=$(find gen/android -name '*.apk' -type f | head -1) + if [ -z "$APK_PATH" ]; then + echo "No APK found" + exit 1 + fi + APK_FILENAME=$(basename "$APK_PATH") + echo "path=$APK_PATH" >> $GITHUB_OUTPUT + echo "filename=$APK_FILENAME" >> $GITHUB_OUTPUT + + - name: Upload APK artifact + uses: actions/upload-artifact@v4 + with: + name: android-apk + path: ${{ steps.find-apk.outputs.path }} + + - name: Upload APK to release + if: needs.get-version.outputs.should-publish != '' + env: + RELEASE_ID: ${{ needs.create-release.outputs.releaseId }} + run: | + curl -X POST -H "Authorization: Bearer $XGH_TOKEN" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@${{ steps.find-apk.outputs.path }}" \ + "https://uploads.github.com/repos/$PUBLISH_REPO/releases/$RELEASE_ID/assets?name=${{ steps.find-apk.outputs.filename }}" + publish-release: runs-on: ubuntu-latest - needs: [get-version, check-version, create-release, package-tauri] + needs: [get-version, check-version, create-release, package-tauri, package-android] environment: Production if: needs.get-version.outputs.should-publish != '' && needs.check-version.outputs.should-skip != 'true' permissions: diff --git a/package.json b/package.json index c6af243b6..7a766dad6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alphahuman", "private": true, - "version": "0.20.0", + "version": "0.21.0", "type": "module", "scripts": { "dev": "vite",