Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 190 additions & 69 deletions .github/workflows/android-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,11 @@ on:
branches: [ master ]

jobs:
build-android:
frontend-build:
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'

- name: Setup Android SDK
uses: android-actions/setup-android@v3

- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
Expand All @@ -36,10 +27,87 @@ jobs:
restore-keys: |
${{ runner.os }}-bun-

- name: Install frontend dependencies
working-directory: ./frontend
run: bun install

- name: Build frontend
working-directory: ./frontend
run: bun run build
env:
VITE_OPEN_SECRET_API_URL: ${{ github.event_name == 'pull_request' && 'https://enclave.secretgpt.ai' || 'https://enclave.trymaple.ai' }}
VITE_MAPLE_BILLING_API_URL: ${{ github.event_name == 'pull_request' && 'https://billing-dev.opensecret.cloud' || 'https://billing.opensecret.cloud' }}
VITE_CLIENT_ID: ba5a14b5-d915-47b1-b7b1-afda52bc5fc6

- name: Upload frontend dist
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: frontend/dist
retention-days: 1

rust-build:
needs: frontend-build
runs-on: ubuntu-latest-8-cores
strategy:
fail-fast: false
matrix:
include:
- rust_target: aarch64-linux-android
target_env: aarch64_linux_android
cargo_target_env: AARCH64_LINUX_ANDROID
abi: arm64-v8a
cc: aarch64-linux-android24-clang
cxx: aarch64-linux-android24-clang++
ranlib_link: aarch64-linux-android-ranlib
- rust_target: armv7-linux-androideabi
target_env: armv7_linux_androideabi
cargo_target_env: ARMV7_LINUX_ANDROIDEABI
abi: armeabi-v7a
cc: armv7a-linux-androideabi24-clang
cxx: armv7a-linux-androideabi24-clang++
ranlib_link: armv7a-linux-androideabi-ranlib
- rust_target: i686-linux-android
target_env: i686_linux_android
cargo_target_env: I686_LINUX_ANDROID
abi: x86
cc: i686-linux-android24-clang
cxx: i686-linux-android24-clang++
ranlib_link: i686-linux-android-ranlib
- rust_target: x86_64-linux-android
target_env: x86_64_linux_android
cargo_target_env: X86_64_LINUX_ANDROID
abi: x86_64
cc: x86_64-linux-android24-clang
cxx: x86_64-linux-android24-clang++
ranlib_link: x86_64-linux-android-ranlib

steps:
- uses: actions/checkout@v4

- name: Download frontend dist
uses: actions/download-artifact@v4
with:
name: frontend-dist
path: frontend-dist

- name: Restore frontend dist
run: |
rm -rf frontend/dist
mkdir -p frontend/dist

if [ -d frontend-dist/dist ]; then
cp -a frontend-dist/dist/. frontend/dist/
elif [ -d frontend-dist/frontend/dist ]; then
cp -a frontend-dist/frontend/dist/. frontend/dist/
else
cp -a frontend-dist/. frontend/dist/
fi
Comment thread
AnthonyRonning marked this conversation as resolved.
Comment on lines +88 to +105

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# First, let's find the relevant configuration files
echo "=== Finding Tauri configuration files ==="
find . -type f \( -name "Cargo.toml" -o -name "build.rs" -o -name "tauri.conf.json" \) | grep -E "(src-tauri|tauri)" | head -20

# Check for frontend/dist references in Cargo.toml
echo -e "\n=== Checking Cargo.toml for frontend/dist references ==="
find . -path "*/src-tauri/Cargo.toml" -exec rg -n 'frontend/dist|dist/|include_dir|embed|frontend.*assets' {} +

# Check for frontend/dist references in build.rs
echo -e "\n=== Checking build.rs for frontend/dist references ==="
find . -path "*/src-tauri/build.rs" -exec rg -n 'frontend/dist|dist/|include_dir|embed|frontend.*assets' {} +

# Check tauri.conf.json for distDir or beforeBuildCommand
echo -e "\n=== Checking tauri.conf.json for distDir or frontend paths ==="
find . -name "tauri.conf.json" -exec cat {} + 2>/dev/null | head -100

# Look for any build script dependencies on frontend
echo -e "\n=== Checking for buildDependencies ==="
find . -name "tauri.conf.json" -exec rg -A 5 '"build"' {} +

Repository: OpenSecretCloud/Maple

Length of output: 3312


🏁 Script executed:

#!/bin/bash

# Find the android-build.yml workflow file
workflow_file=".github/workflows/android-build.yml"

if [ ! -f "$workflow_file" ]; then
  echo "Workflow file not found"
  exit 1
fi

# Extract the frontend-build job to see artifact upload
echo "=== Frontend-build job artifact upload section ==="
sed -n '/frontend-build:/,/rust-build:/p' "$workflow_file" | tail -20

# Also check the exact upload step
echo -e "\n=== Looking for upload-artifact step in frontend-build ==="
sed -n '/frontend-build:/,/rust-build:/p' "$workflow_file" | rg -A 10 'upload-artifact'

Repository: OpenSecretCloud/Maple

Length of output: 1112


Frontend dist is required for Tauri Android builds, but the restore logic is fragile and lacks error handling.

The rust-build job correctly downloads the frontend dist artifact—Tauri's tauri.conf.json specifies "frontendDist": "../dist", which tells Tauri to embed frontend assets during the Rust build. This is necessary for Android packaging and not redundant.

However, the restore logic (lines 94-105) attempts three different fallback paths without validation, suggesting uncertainty about the artifact structure. If the artifact is unexpectedly structured or missing, the build could fail silently or produce an incorrect app without clear error messaging. Since frontend-build uploads path: frontend/dist, the downloaded artifact should have contents directly in the frontend-dist/ directory, making the multiple fallback logic unnecessary.

Consider simplifying the restore step to a single path with explicit error handling to prevent silent failures.

🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 88 - 105, The restore step
"Restore frontend dist" is fragile; replace the three-way fallback with a
single, explicit restore from the downloaded artifact (copy frontend-dist/. into
frontend/dist/) and add explicit validation and failure: after creating
frontend/dist, verify frontend-dist exists and is non-empty, then cp -a
frontend-dist/. frontend/dist/; if the check fails, emit a clear error message
and exit non-zero so the rust-build job fails fast. Ensure this change is
applied to the step named "Restore frontend dist" that follows the "Download
frontend dist" action.


- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android,i686-linux-android
targets: ${{ matrix.rust_target }}

- name: Setup Android NDK
uses: nttld/setup-ndk@v1
Expand All @@ -48,16 +116,6 @@ jobs:
ndk-version: r27c
add-to-path: true

- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Install sccache
run: |
SCCACHE_VERSION=0.8.2
Expand All @@ -71,11 +129,90 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.cache/sccache
key: ${{ runner.os }}-sccache-android-${{ hashFiles('**/Cargo.lock') }}
key: ${{ runner.os }}-sccache-android-${{ matrix.rust_target }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-sccache-android-${{ matrix.rust_target }}-
${{ runner.os }}-sccache-android-
${{ runner.os }}-sccache-

- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y libssl-dev

- name: Configure sccache
run: |
echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV
echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV

- name: Build Rust library (${{ matrix.rust_target }})
run: |
export NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}
export PATH=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH

# C toolchain env for build scripts (e.g. openssl-sys)
export AR_${{ matrix.target_env }}=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
export CC_${{ matrix.target_env }}=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/${{ matrix.cc }}
export CXX_${{ matrix.target_env }}=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/${{ matrix.cxx }}
export RANLIB_${{ matrix.target_env }}=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib

# Explicit linker for cargo (belt + suspenders)
export CARGO_TARGET_${{ matrix.cargo_target_env }}_LINKER=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/${{ matrix.cc }}

# Create ranlib symlink that OpenSSL expects
sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/local/bin/${{ matrix.ranlib_link }}

cargo build --manifest-path frontend/src-tauri/Cargo.toml --release --target ${{ matrix.rust_target }} --lib

mkdir -p artifacts
cp frontend/src-tauri/target/${{ matrix.rust_target }}/release/libapp_lib.so artifacts/libapp_lib-${{ matrix.abi }}.so

- name: Show sccache stats
run: sccache --show-stats

- name: Upload Rust library (${{ matrix.abi }})
uses: actions/upload-artifact@v4
with:
name: rust-lib-${{ matrix.abi }}
path: artifacts/libapp_lib-${{ matrix.abi }}.so
retention-days: 1

build-android:
needs: rust-build
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'

- name: Setup Android SDK
uses: android-actions/setup-android@v3

Comment on lines +187 to +201

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing download of frontend-dist artifact. The build-android job needs the frontend assets to package into the APK/AAB. Without this, the Android package will be missing the web UI.

Add before the "Setup Java" step:

Suggested change
build-android:
needs: rust-build
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
build-android:
needs: rust-build
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
- name: Download frontend dist
uses: actions/download-artifact@v4
with:
name: frontend-dist
path: frontend/dist
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 181:195

Comment:
Missing download of `frontend-dist` artifact. The `build-android` job needs the frontend assets to package into the APK/AAB. Without this, the Android package will be missing the web UI.

Add before the "Setup Java" step:

```suggestion
  build-android:
    needs: rust-build
    runs-on: ubuntu-latest-8-cores
    steps:
      - uses: actions/checkout@v4

      - name: Download frontend dist
        uses: actions/download-artifact@v4
        with:
          name: frontend-dist
          path: frontend/dist

      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '21'
```

How can I resolve this? If you propose a fix, please make it concise.

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Setup Android NDK
uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r27c
add-to-path: true

- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

Comment on lines +216 to 225

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Gradle cache key may not function correctly.

The cache key pattern references frontend/src-tauri/gen/android/**/*.gradle* and frontend/src-tauri/gen/android/gradle-wrapper.properties, but these files are generated during the workflow (lines 224-342), not committed to the repository.

This means:

  • On the first run, the cache key will hash empty/non-existent files
  • Cache restoration will likely never match across runs
  • The Gradle cache may not provide the intended performance benefit
♻️ Recommended fix

Consider using a simpler, more reliable cache key that doesn't depend on generated files:

       - name: Cache Gradle
         uses: actions/cache@v4
         with:
           path: |
             ~/.gradle/caches
             ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties') }}
+          key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/Cargo.lock', 'frontend/src-tauri/tauri.conf.json') }}
           restore-keys: |
             ${{ runner.os }}-gradle-

This uses committed files that actually influence the Gradle build.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Cache Gradle
uses: actions/cache@v4
with:
path: ~/.cargo/bin/
key: ${{ runner.os }}-cargo-bin-tauri-cli-2.9.2
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-cargo-bin-tauri-cli-
${{ runner.os }}-cargo-bin-
${{ runner.os }}-gradle-
- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/Cargo.lock', 'frontend/src-tauri/tauri.conf.json') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Cache Cargo bin (Tauri CLI)
uses: actions/cache@v4
with:
Expand All @@ -90,10 +227,6 @@ jobs:
sudo apt-get update
sudo apt-get install -y libssl-dev

- name: Install frontend dependencies
working-directory: ./frontend
run: bun install

- name: Install Tauri CLI
run: |
if ! command -v cargo-tauri &> /dev/null; then
Expand All @@ -104,6 +237,17 @@ jobs:
env:
CARGO_CFG_TARGET_OS: linux

- name: Initialize Tauri Android project
working-directory: ./frontend
run: |
export ANDROID_HOME=$ANDROID_SDK_ROOT
cargo tauri android init --ci --skip-targets-install
Comment thread
AnthonyRonning marked this conversation as resolved.
Outdated

- name: Verify Tauri Android Gradle files
run: |
test -f frontend/src-tauri/gen/android/tauri.settings.gradle
test -f frontend/src-tauri/gen/android/app/tauri.build.gradle.kts

- name: Setup Android signing
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
Expand Down Expand Up @@ -132,56 +276,33 @@ jobs:

echo "Generated tauri.properties with version $VERSION and versionCode $VERSION_CODE"

- name: Configure sccache
- name: Download Rust libraries
uses: actions/download-artifact@v4
with:
pattern: rust-lib-*
merge-multiple: true
path: rust-libs

- name: Install prebuilt Rust libraries
run: |
echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV
echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64

- name: Build Tauri Android App (Signed Release)
working-directory: ./frontend
cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
Comment on lines +384 to +394

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing validation: The workflow should verify that all 4 required Rust libraries exist before attempting to copy them. With fail-fast: false in the rust-build matrix, if one architecture build fails, the build-android job will still start but with missing libraries, causing the cp commands to fail with unclear error messages.

Recommendation: Add a verification step before copying:

Suggested change
- name: Install prebuilt Rust libraries
run: |
echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV
echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64
- name: Build Tauri Android App (Signed Release)
working-directory: ./frontend
cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
- name: Install prebuilt Rust libraries
run: |
# Verify all required libraries exist
for abi in arm64-v8a armeabi-v7a x86 x86_64; do
if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
echo "ERROR: Missing Rust library for ${abi}"
exit 1
fi
done
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64
cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so

This provides clearer error messages if a library is missing.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 286:296

Comment:
**Missing validation**: The workflow should verify that all 4 required Rust libraries exist before attempting to copy them. With `fail-fast: false` in the rust-build matrix, if one architecture build fails, the build-android job will still start but with missing libraries, causing the `cp` commands to fail with unclear error messages.

**Recommendation**: Add a verification step before copying:

```suggestion
      - name: Install prebuilt Rust libraries
        run: |
          # Verify all required libraries exist
          for abi in arm64-v8a armeabi-v7a x86 x86_64; do
            if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
              echo "ERROR: Missing Rust library for ${abi}"
              exit 1
            fi
          done
          
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64

          cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
          cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
          cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
          cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
```

This provides clearer error messages if a library is missing.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +384 to +394

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing verification that downloaded artifacts exist before copying. If artifact download fails or is incomplete, cp will fail with unclear error message.

Consider adding verification:

# Verify all artifacts exist
for abi in arm64-v8a armeabi-v7a x86 x86_64; do
  if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
    echo "Error: Missing rust-libs/libapp_lib-${abi}.so"
    exit 1
  fi
done

# Then copy them
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86,x86_64}
cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
# ... rest of copies
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 286:296

Comment:
Missing verification that downloaded artifacts exist before copying. If artifact download fails or is incomplete, `cp` will fail with unclear error message.

Consider adding verification:
```bash
# Verify all artifacts exist
for abi in arm64-v8a armeabi-v7a x86 x86_64; do
  if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
    echo "Error: Missing rust-libs/libapp_lib-${abi}.so"
    exit 1
  fi
done

# Then copy them
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86,x86_64}
cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
# ... rest of copies
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +384 to +394

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add validation to fail fast with a clear message if any Rust library is missing. With fail-fast: false in the matrix, if one ABI build fails, this step will produce a confusing cp: cannot stat error.

      - name: Install prebuilt Rust libraries
        run: |
          # Validate all required libraries exist
          for abi in arm64-v8a armeabi-v7a x86 x86_64; do
            if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
              echo "Error: Missing Rust library for ${abi}"
              echo "One of the rust-build matrix jobs likely failed"
              exit 1
            fi
          done

          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64

          cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
          cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
          cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
          cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 305:315

Comment:
Add validation to fail fast with a clear message if any Rust library is missing. With `fail-fast: false` in the matrix, if one ABI build fails, this step will produce a confusing `cp: cannot stat` error.

```
      - name: Install prebuilt Rust libraries
        run: |
          # Validate all required libraries exist
          for abi in arm64-v8a armeabi-v7a x86 x86_64; do
            if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
              echo "Error: Missing Rust library for ${abi}"
              echo "One of the rust-build matrix jobs likely failed"
              exit 1
            fi
          done

          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64

          cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
          cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
          cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
          cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +384 to +394

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add validation before copying to ensure all required libraries exist

Suggested change
- name: Install prebuilt Rust libraries
run: |
echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV
echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64
- name: Build Tauri Android App (Signed Release)
working-directory: ./frontend
cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
- name: Install prebuilt Rust libraries
run: |
# Validate all required libraries exist
for abi in arm64-v8a armeabi-v7a x86 x86_64; do
if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
echo "Error: Missing required library for ${abi}"
exit 1
fi
done
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64
cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 379:389

Comment:
add validation before copying to ensure all required libraries exist

```suggestion
      - name: Install prebuilt Rust libraries
        run: |
          # Validate all required libraries exist
          for abi in arm64-v8a armeabi-v7a x86 x86_64; do
            if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
              echo "Error: Missing required library for ${abi}"
              exit 1
            fi
          done

          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
          mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64

          cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
          cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
          cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
          cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +377 to +394

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Verify all required library artifacts were downloaded.

The step downloads artifacts with pattern matching but doesn't verify that all 4 expected .so files exist before attempting to copy them. If a matrix job failed silently or the artifact wasn't uploaded, the copy commands would fail.

♻️ Proposed safeguard to validate all libraries exist
       - name: Install prebuilt Rust libraries
         run: |
+          # Verify all required libraries were downloaded
+          for abi in arm64-v8a armeabi-v7a x86 x86_64; do
+            if [ ! -f "rust-libs/libapp_lib-${abi}.so" ]; then
+              echo "ERROR: Missing libapp_lib-${abi}.so"
+              echo "Downloaded files:"
+              ls -la rust-libs/
+              exit 1
+            fi
+          done
+
           mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
           mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a
           mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86
           mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64
 
           cp rust-libs/libapp_lib-arm64-v8a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/libapp_lib.so
           cp rust-libs/libapp_lib-armeabi-v7a.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/libapp_lib.so
           cp rust-libs/libapp_lib-x86.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/libapp_lib.so
           cp rust-libs/libapp_lib-x86_64.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/libapp_lib.so
🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 377 - 394, The workflow's
"Install prebuilt Rust libraries" step blindly runs cp for four .so files
(rust-libs/libapp_lib-arm64-v8a.so, libapp_lib-armeabi-v7a.so,
libapp_lib-x86.so, libapp_lib-x86_64.so) without verifying they were downloaded;
add a pre-check in that step to verify each of those four files exists in
rust-libs, print which are missing if any, and exit non-zero to fail the job
before attempting the cp commands so you avoid partial/no-op copies and get a
clear error when an artifact is missing.


- name: Build Android APK + AAB (Signed Release)
working-directory: ./frontend/src-tauri/gen/android
run: |
export ANDROID_HOME=$ANDROID_SDK_ROOT
export NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}

# Set up Android NDK toolchain paths
export PATH=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH

# Set up cross-compilation environment variables for each target
export AR_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
export CC_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang
export CXX_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++
export RANLIB_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib

export AR_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
export CC_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang
export CXX_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang++
export RANLIB_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib

export AR_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
export CC_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang
export CXX_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++
export RANLIB_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib

export AR_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
export CC_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang
export CXX_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang++
export RANLIB_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib

# Create symlinks for ranlib that OpenSSL expects
sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/local/bin/aarch64-linux-android-ranlib
sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/local/bin/armv7a-linux-androideabi-ranlib
sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/local/bin/x86_64-linux-android-ranlib
sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/local/bin/i686-linux-android-ranlib

cargo tauri android build
env:
VITE_OPEN_SECRET_API_URL: ${{ github.event_name == 'pull_request' && 'https://enclave.secretgpt.ai' || 'https://enclave.trymaple.ai' }}
VITE_MAPLE_BILLING_API_URL: ${{ github.event_name == 'pull_request' && 'https://billing-dev.opensecret.cloud' || 'https://billing.opensecret.cloud' }}
VITE_CLIENT_ID: ba5a14b5-d915-47b1-b7b1-afda52bc5fc6

- name: Show sccache stats
run: sccache --show-stats
./gradlew :app:assembleUniversalRelease :app:bundleUniversalRelease -PskipRustBuild=true

- name: Upload Android APK
uses: actions/upload-artifact@v4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ open class BuildTask : DefaultTask() {

@TaskAction
fun assemble() {
if (shouldSkipRustBuild()) {
val target = target ?: throw GradleException("target cannot be null")
val lib = expectedJniLib(target)
if (!lib.exists()) {
throw GradleException(
"skipRustBuild=true but prebuilt Rust library is missing at ${lib.absolutePath}"
)
}

project.logger.lifecycle("skipRustBuild=true; using prebuilt Rust library at ${lib.absolutePath}")
return
}

val userHome = System.getProperty("user.home")
val executable = if (File("$userHome/.bun/bin/bun").exists()) {
"$userHome/.bun/bin/bun"
Expand All @@ -33,6 +46,23 @@ open class BuildTask : DefaultTask() {
}
}

private fun shouldSkipRustBuild(): Boolean {
val raw = project.findProperty("skipRustBuild")?.toString() ?: return false
return raw.equals("true", ignoreCase = true) || raw == "1" || raw.equals("yes", ignoreCase = true)
}

private fun expectedJniLib(target: String): File {
val abi = when (target) {
"aarch64" -> "arm64-v8a"
"armv7" -> "armeabi-v7a"
"i686" -> "x86"
"x86_64" -> "x86_64"
else -> throw GradleException("Unknown target '$target'")
}

return File(project.projectDir, "src/main/jniLibs/$abi/libapp_lib.so")
}

fun runTauriCli(executable: String) {
val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null")
val target = target ?: throw GradleException("target cannot be null")
Expand Down
Loading