-
Notifications
You must be signed in to change notification settings - Fork 5
ci: Refactor android build pipeline #377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Warning Rate limit exceeded@AnthonyRonning has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 54 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAndroid CI was split from a monolithic build into a staged, multi-job pipeline (frontend build → tauri gradle generation → matrixed per-ABI Rust builds → packaging); several workflows had runner labels upgraded to higher-capacity variants and top-level env vars were added for frontend. Changes
Sequence Diagram(s)sequenceDiagram
participant FE as build-frontend
participant Art as GitHub Artifacts
participant Gen as generate-gradle-files
participant Rust as build-rust (matrix)
participant Pack as package-android
participant Gradle as Gradle
FE->>Art: upload `frontend-dist`
Gen->>Art: upload `tauri-android-generated`
Rust->>Art: for each ABI upload `android-lib-<ABI>.so`
Pack->>Art: download `frontend-dist`, `tauri-android-generated`, all `.so`
Pack->>Pack: place `.so` into `app/src/main/jniLibs/<ABI>/`
Pack->>Pack: generate `tauri.properties` and signing config
Pack->>Gradle: run APK/AAB build tasks (parallel)
Gradle->>Pack: return APK / AAB
Pack->>Art: upload final artifacts
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Deploying maple with
|
| Latest commit: |
79e2d43
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://2637ddfd.maple-ca8.pages.dev |
| Branch Preview URL: | https://upgrade-github-actions-runne.maple-ca8.pages.dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR upgrades all GitHub Actions workflows to use larger runners for improved build performance:
Linux workflows transition from ubuntu-latest (2 CPU, 7GB) to ubuntu-latest-8-cores (8 CPU, 32GB RAM, 300GB SSD):
android-build.yml- Benefits Android builds that compile 4 targets in parallelclaude.yml- Speeds up Claude Code automation tasksdesktop-build.yml(build-linux job) - Accelerates Linux desktop buildsrelease.yml(3 jobs: create-release, build-android, update-latest-json) - Improves release pipelinetestflight-on-comment.yml(check-comment job) - Faster permission checks
macOS workflows upgrade from macos-latest (3-core M1, 7GB) to macos-latest-xlarge (M2, 5 cores + 8 GPU, 14GB RAM):
desktop-build.yml(build-macos job) - Leverages M2 for universal binary compilationmobile-build.yml(build-ios job) - Accelerates iOS builds and TestFlight submissionsrelease.yml(build-tauri matrix) - Speeds up release builds for macOStestflight-on-comment.yml(deploy-testflight job) - Faster TestFlight deployments
The changes are consistent across all files. In release.yml, all conditional checks comparing matrix.platform were correctly updated to use the new runner names. The PR description clearly documents that ubuntu-latest-8-cores must be manually created in organization settings before merging, while macos-latest-xlarge is a standard GitHub-hosted runner requiring no setup.
Expected Impact: Significantly faster Rust compilation (4x more cores for Linux), improved Android multi-target builds, and better macOS universal binary performance with M2 chips.
Confidence Score: 5/5
- This PR is safe to merge once the ubuntu-latest-8-cores runner is created in organization settings
- All workflow changes are straightforward runner label replacements with no logic modifications. The changes are consistent across all 6 files, and all conditional checks in release.yml correctly reference the new runner names. The PR description clearly documents the setup requirement for the Ubuntu runner, and the syntax is valid throughout.
- No files require special attention - all changes follow the same simple pattern of updating runner labels
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 5/5 | Changed runner from ubuntu-latest to ubuntu-latest-8-cores for Android builds, requires manual setup before merging |
| .github/workflows/claude.yml | 5/5 | Changed runner from ubuntu-latest to ubuntu-latest-8-cores for Claude Code automation, requires manual setup before merging |
| .github/workflows/desktop-build.yml | 5/5 | Updated both macOS (to macos-latest-xlarge) and Linux (to ubuntu-latest-8-cores) runners for desktop builds |
| .github/workflows/mobile-build.yml | 5/5 | Changed iOS build runner from macos-latest to macos-latest-xlarge for faster builds |
| .github/workflows/release.yml | 5/5 | Updated all jobs to use larger runners, correctly updated matrix platform conditionals to match new runner names |
| .github/workflows/testflight-on-comment.yml | 5/5 | Updated both check-comment (ubuntu) and deploy-testflight (macOS) jobs to use larger runners |
Sequence Diagram
sequenceDiagram
participant Dev as Developer
participant GHA as GitHub Actions
participant OrgAdmin as Org Admin
participant Ubuntu as ubuntu-latest-8-cores
participant MacOS as macos-latest-xlarge
Note over Dev,MacOS: PR #377: Runner Upgrade Flow
Dev->>GHA: Push to master/PR
alt Ubuntu Runner Setup Required
GHA->>OrgAdmin: Workflow fails (runner not found)
OrgAdmin->>GHA: Create ubuntu-latest-8-cores runner
Note over OrgAdmin,GHA: Org Settings → New Runner<br/>8-core, 32GB RAM, 300GB SSD
end
par Desktop Build (macOS)
GHA->>MacOS: build-macos job
MacOS->>MacOS: Universal binary (M2, 5 cores, 14GB)
MacOS->>GHA: Upload DMG artifacts
and Desktop Build (Linux)
GHA->>Ubuntu: build-linux job
Ubuntu->>Ubuntu: Linux build (8 CPU, 32GB)
Ubuntu->>GHA: Upload AppImage/DEB
and Mobile Build (iOS)
GHA->>MacOS: build-ios job
MacOS->>MacOS: iOS build + TestFlight
MacOS->>GHA: Upload IPA
and Android Build
GHA->>Ubuntu: build-android job
Ubuntu->>Ubuntu: 4 target builds (parallel)
Ubuntu->>GHA: Upload APK/AAB
and Claude Automation
GHA->>Ubuntu: claude job
Ubuntu->>Ubuntu: Run Claude Code
Ubuntu->>GHA: Results
end
Note over Dev,MacOS: All workflows now use larger runners<br/>for faster compilation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/release.yml (1)
52-88: Includematrix.platformin the sccache cache key.The sccache cache is platform-specific: macOS uses Homebrew while Linux uses a downloaded binary, producing incompatible caches. Using
runner.osalone risks restoring macOS cache on Linux (or vice versa). Update the key to:- key: ${{ runner.os }}-sccache-release-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.platform }}-sccache-release-${{ hashFiles('**/Cargo.lock') }}(The
~expansion inactions/cacheis reliable, including in conditional expressions—no concern there.)
🧹 Nitpick comments (2)
.github/workflows/release.yml (2)
323-326: Consider keepingupdate-latest-jsonon standardubuntu-latest.
This job is mostlygh+ file generation; using the large runner increases cost and failure modes without much speedup.Proposed diff
update-latest-json: needs: build-tauri - runs-on: ubuntu-latest-8-cores + runs-on: ubuntu-latest
32-38: Consider pinning the Ubuntu runner version explicitly.The workflow uses
ubuntu-latest-8-cores, which currently resolves to Ubuntu 24.04. For clarity and to avoid unexpected changes when GitHub updates runner images, useubuntu-24.04-8-coresinstead. This makes the Ubuntu version dependency explicit in the code rather than relying on GitHub's label mappings.(Note:
libwebkit2gtk-4.1-devitself is available on both Ubuntu 22.04 and 24.04, so it doesn't force a specific version—the Ubuntu 24.04 assumption comes from the-latestlabel.)
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
.github/workflows/android-build.yml.github/workflows/claude.yml.github/workflows/desktop-build.yml.github/workflows/mobile-build.yml.github/workflows/release.yml.github/workflows/testflight-on-comment.yml
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/release.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-ios
- GitHub Check: build-android
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-linux
- GitHub Check: Cloudflare Pages
🔇 Additional comments (11)
.github/workflows/mobile-build.yml (1)
11-11: LGTM! Valid upgrade to M2-powered runner.The
macos-latest-xlargerunner uses a 5 vCPU M2 Pro machine, providing improved performance for iOS builds..github/workflows/desktop-build.yml (2)
11-11: LGTM! Valid upgrade to M2-powered runner.The macOS build will benefit from the enhanced M2 Pro hardware with 5 cores for faster universal builds.
117-117: LGTM! Upgrade to 8-core runner.The Linux build will benefit from 4× more cores (8 vs 2) for faster Rust compilation.
.github/workflows/claude.yml (1)
33-33: LGTM! Upgrade to 8-core runner.The Claude automation workflow will benefit from the additional compute resources.
.github/workflows/android-build.yml (1)
11-11: LGTM! Upgrade to 8-core runner.The 8-core runner will significantly improve parallel compilation of the 4 Android targets (aarch64, armv7, x86_64, i686).
.github/workflows/testflight-on-comment.yml (3)
15-15: LGTM! Upgrade to 8-core runner.The permission check job will benefit from the enhanced runner resources.
67-67: LGTM! Valid upgrade to M2-powered runner.The TestFlight deployment will benefit from the M2 Pro hardware for faster iOS builds.
15-15: Remove the "Also applies to: 67-67" reference—only line 15 requires verification.Line 15 correctly uses
ubuntu-latest-8-cores, a custom runner that must be manually created in your organization's Actions runner settings before merging. However, line 67 usesmacos-latest-xlarge, which is a GitHub-provided larger runner label and does not require custom setup.To proceed, ensure the following is completed:
- Navigate to organization Actions runner settings
- Create a new GitHub-hosted runner named
ubuntu-latest-8-cores- Configure it with Ubuntu 24.04 (or 22.04) and 8-core size (8 CPU, 32GB RAM, 300GB SSD)
Likely an incorrect or invalid review comment.
.github/workflows/release.yml (3)
133-136: Runner upgrade for Android build makes sense; just note it’s now dependent on the custom runner existing.
No functional concerns in this diff itself.
10-12: No action needed. Theubuntu-latest-8-coreslabel is an official GitHub-hosted larger runner (not a custom organization-created runner), so there is no "blast radius" risk from tying the job to it. The choice to use an 8-core runner for the release job is likely intentional for build performance and is a standard GitHub Actions feature.Likely an incorrect or invalid review comment.
71-80: No action needed. Theubuntu-latest-8-coresrunner already uses Ubuntu 24.04, andlibwebkit2gtk-4.1-devis available and installable on Ubuntu 22.04 (in the universe repository) with versions ranging from 2.36.x to 2.50.x. The package will not fail on either version.Likely an incorrect or invalid review comment.
| - name: Install Rust | ||
| uses: dtolnay/rust-toolchain@stable | ||
| with: | ||
| targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} | ||
| targets: ${{ matrix.platform == 'macos-latest-xlarge' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
dtolnay/rust-toolchain action targets empty string parameter
💡 Result:
Short answer: don’t pass an empty string to the targets input — instead make the rust-toolchain step conditional so it only runs when a target is present.
Why: dtolnay/rust-toolchain’s inputs expect a comma-separated list of target triples; giving an empty string can be interpreted as “install nothing” or can cause rustup to be invoked with an empty argument. The action’s docs show the targets input is a comma-separated string. [1]
How to fix: condition the step on the matrix value (or on the variable) being non-empty. Example:
- name: Install toolchain
if: ${{ matrix.target != '' }}
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
You can use GitHub Actions expressions to compare to the empty string as shown above. [2]
References:
- dtolnay/rust-toolchain README (inputs: targets). [1]
- GitHub Actions expressions / conditionals (string / empty-string behavior). [2]
🏁 Script executed:
cat -n .github/workflows/release.yml | sed -n '40,60p'Repository: OpenSecretCloud/Maple
Length of output: 908
Split Rust installation into conditional steps to avoid empty targets parameter.
The dtolnay/rust-toolchain action does not handle an empty string for the targets input; passing targets: "" causes workflow failures. Use conditional steps instead to install the toolchain only when targets are needed.
Proposed diff
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- with:
- targets: ${{ matrix.platform == 'macos-latest-xlarge' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
+ if: matrix.platform != 'macos-latest-xlarge'
+
+ - name: Install Rust (macOS universal targets)
+ if: matrix.platform == 'macos-latest-xlarge'
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ targets: aarch64-apple-darwin,x86_64-apple-darwinThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Upgrades all GitHub Actions workflows to use larger runners for improved build performance. Linux workflows now use ubuntu-latest-8-cores (8 CPU, 32GB RAM) and macOS workflows use macos-latest-xlarge (M2, 5 cores). The Android build workflow was also refactored to split builds into three parallel jobs, enabling simultaneous compilation of all four Rust targets.
Confidence Score: 4/5
- Safe to merge after creating the ubuntu-latest-8-cores runner in organization settings
- All runner configuration changes are syntactically correct and consistent across workflows. The macOS xlarge runner works automatically, but the PR description correctly notes that the Ubuntu 8-core runner must be manually created in organization settings before merging, which is a prerequisite configuration step rather than a code issue.
- .github/workflows/android-build.yml requires verification that the refactored multi-job workflow produces identical artifacts
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 4/5 | Refactored to split Android build into 3 jobs (frontend, parallel Rust targets, Gradle packaging) using ubuntu-latest-8-cores runners; significantly improves build parallelism |
Sequence Diagram
sequenceDiagram
participant Frontend as build-frontend
participant Matrix as build-rust (matrix)
participant Package as package-android
participant Artifacts as Outputs
Frontend->>Frontend: "Build frontend with Bun"
Frontend->>Matrix: "Upload frontend-dist artifact"
par Parallel Rust builds
Matrix->>Matrix: "Build aarch64 (arm64-v8a)"
Matrix->>Matrix: "Build armv7 (armeabi-v7a)"
Matrix->>Matrix: "Build i686 (x86)"
Matrix->>Matrix: "Build x86_64"
end
Matrix->>Package: "Upload 4 .so artifacts"
Package->>Package: "Download frontend-dist"
Package->>Package: "Download all .so files"
Package->>Package: "Place in jniLibs directories"
Package->>Package: "Run Gradle (APK & AAB)"
Package->>Artifacts: "Upload APK and AAB"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.github/workflows/android-build.yml:
- Around line 86-93: The workflow step that installs sccache downloads and
executes an archive without validating its integrity; change the "Install
sccache" step to first download the tarball and its corresponding .sha256
checksum (using SCCACHE_VERSION / SCCACHE_URL), verify the tarball with
sha256sum -c (failing the job if verification fails), only then extract the
archive and run sudo mv / chmod on the verified binary; ensure you stop piping
curl into tar and instead write files to disk so the checksum can be validated
before extraction or installation.
🧹 Nitpick comments (4)
.github/workflows/android-build.yml (4)
16-17: Current job dependencies block parallelism (Rust doesn’t need to wait for frontend).
build-rustdoesn’t consumefrontend-dist, soneeds: build-frontendforces unnecessary serialization; let them run concurrently and makepackage-androiddepend on both.Proposed diff
build-rust: runs-on: ubuntu-latest-8-cores - needs: build-frontend strategy: fail-fast: false @@ package-android: runs-on: ubuntu-latest-8-cores - needs: build-rust + needs: [build-frontend, build-rust]Also applies to: 52-55, 174-176
36-43: Use frozen installs in CI for Bun.Prefer failing on lockfile drift to keep CI deterministic.
Proposed diff
- name: Install frontend dependencies working-directory: ./frontend - run: bun install + run: bun install --frozen-lockfile @@ - name: Install frontend dependencies working-directory: ./frontend - run: bun install + run: bun install --frozen-lockfileAlso applies to: 221-224
231-251: Make native-lib placement step fail fast and clearer when artifacts are missing.This step will currently fail on missing artifacts, but adding strict shell flags makes failures more diagnosable (and avoids partial copies).
Proposed diff
- name: Place native libraries in jniLibs run: | + set -euo pipefail # Create jniLibs directories mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86,x86_64}
118-156: Hard-coded API level 24 matches your current minSdk, but consider parameterizing it for maintainability.The workflow uses
*android24-clangwhich currently aligns with yourminSdk = 24in build.gradle.kts. However, hard-coding this value in the workflow separate from the Gradle config creates a maintenance risk: if minSdk changes in the future, you'd need to remember to update both places. Consider extracting the Android API level into a shared configuration or environment variable to keep it in sync.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-frontend
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
.github/workflows/android-build.yml (1)
9-13: Double-check PR vs push env routing for Vite endpoints.The ternary expression will embed different backend URLs depending on
github.event_name; make sure PR builds should indeed point athttps://enclave.secretgpt.ai/billing-dev...and pushes to master athttps://enclave.trymaple.ai/billing....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR upgrades all GitHub Actions workflows to use larger, faster runners for improved build performance.
Runner Upgrades:
- macOS:
macos-latest→macos-latest-xlarge(M2, 5 cores + 8 GPU, 14GB RAM) - Linux:
ubuntu-latest→ubuntu-latest-8-cores(8 CPU, 32GB RAM, 300GB SSD)
Key Changes:
-
Simple Runner Upgrades (5 workflows):
claude.yml,desktop-build.yml,mobile-build.yml,release.yml, andtestflight-on-comment.ymlonly changeruns-ondirectives and update conditional checks from old to new runner names. -
Android Build Restructure (
android-build.yml): Beyond the runner upgrade, this workflow was significantly refactored into a 3-stage pipeline:- Stage 1 (
build-frontend): Builds frontend once, uploadsfrontend-distartifact - Stage 2 (
build-rust): Matrix job compiling 4 Android targets in parallel (aarch64, armv7, i686, x86_64), each uploading native.solibraries - Stage 3 (
package-android): Downloads all artifacts, places native libs injniLibs/directories, and runs Gradle to produce APK/AAB
The restructure eliminates Tauri CLI usage in favor of manual Rust builds + Gradle packaging, enabling true parallelization of the expensive cross-compilation step.
- Stage 1 (
-
Environment Variables: Android workflow moves
VITE_*variables from step-level to workflow-level for cleaner sharing across jobs.
Setup Note: The ubuntu-latest-8-cores runner must be manually created in GitHub org settings before workflows will function.
Confidence Score: 4/5
- Safe to merge after creating the ubuntu-latest-8-cores runner in org settings. No breaking changes to build logic.
- The PR is mostly safe - it's primarily runner upgrades with one significant architectural change (Android build parallelization). The macOS runner works automatically, but the custom Linux runner must be created first or all Linux/Android builds will fail. The Android restructure appears sound: gen/android is committed, artifacts flow correctly, and the manual Gradle approach mirrors release.yml's existing pattern. One minor inefficiency: package-android unnecessarily runs
bun installbefore downloading pre-built artifacts. - .github/workflows/android-build.yml requires the ubuntu-latest-8-cores runner to be created in org settings before it will work
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 4/5 | Refactored to use ubuntu-latest-8-cores runner; restructured into 3-stage pipeline (build-frontend, build-rust with matrix, package-android) for parallel builds. Removed Tauri CLI usage in favor of manual Gradle builds. Environment variables moved to workflow level. |
| .github/workflows/claude.yml | 5/5 | Simple runner upgrade from ubuntu-latest to ubuntu-latest-8-cores. No other changes. |
| .github/workflows/desktop-build.yml | 5/5 | Runner upgrades: macos-latest to macos-latest-xlarge and ubuntu-latest to ubuntu-latest-8-cores. No other logic changes. |
| .github/workflows/mobile-build.yml | 5/5 | Simple runner upgrade from macos-latest to macos-latest-xlarge. No other changes. |
| .github/workflows/release.yml | 5/5 | Runner upgrades across all jobs: ubuntu-latest to ubuntu-latest-8-cores, macos-latest to macos-latest-xlarge. Updated conditional checks throughout to reference new runner names. |
| .github/workflows/testflight-on-comment.yml | 5/5 | Runner upgrades: ubuntu-latest to ubuntu-latest-8-cores and macos-latest to macos-latest-xlarge. No other logic changes. |
Sequence Diagram
sequenceDiagram
participant GH as GitHub Actions
participant BF as build-frontend
participant BR as build-rust (matrix x4)
participant PA as package-android
participant Artifacts as Artifact Storage
Note over GH: Trigger: push/PR to master
GH->>BF: Start job (ubuntu-latest-8-cores)
BF->>BF: Setup Bun & install deps
BF->>BF: Build frontend (bun run build)
BF->>Artifacts: Upload frontend-dist
BF->>BR: Trigger build-rust (needs: build-frontend)
par Build 4 targets in parallel
BR->>BR: aarch64-linux-android (ubuntu-latest-8-cores)
BR->>BR: armv7-linux-androideabi (ubuntu-latest-8-cores)
BR->>BR: i686-linux-android (ubuntu-latest-8-cores)
BR->>BR: x86_64-linux-android (ubuntu-latest-8-cores)
end
BR->>BR: Setup NDK & Rust toolchain (each)
BR->>BR: Configure cross-compilation env
BR->>BR: cargo build --release --target {target} --lib
BR->>Artifacts: Upload android-lib-{short_name} (x4)
BR->>PA: Trigger package-android (needs: build-rust)
PA->>PA: Setup Java, Android SDK, NDK
PA->>Artifacts: Download frontend-dist
PA->>Artifacts: Download all android-lib-* artifacts
PA->>PA: Place .so files in jniLibs/{arch} dirs
PA->>PA: Setup Android signing & tauri.properties
PA->>PA: ./gradlew assembleUniversalRelease bundleUniversalRelease
PA->>Artifacts: Upload APK & AAB artifacts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
.github/workflows/android-build.yml (2)
94-102: Consider larger sccache size with 32GB RAM.The per-target cache isolation using
matrix.short_nameis correct for parallel builds. However, with 32GB RAM available on the 8-core runner, the 2G sccache limit (set at line 122) might be conservative—consider testing with 4-5G if build times remain slow.
225-227: Remove redundant frontend dependency installation.The
package-androidjob downloads the pre-builtfrontend-distartifact (lines 229-233) and readstauri.conf.jsonfrom the checked-out repo (line 270). Installing frontend dependencies here appears unnecessary and wastes build time on the 8-core runner.♻️ Proposed fix: Remove the redundant install step
- - name: Install frontend dependencies - working-directory: ./frontend - run: bun install - - name: Download frontend distNote: If frontend dependencies are needed for some reason (e.g., a post-build script), please document why.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-rust (x86_64-linux-android, x86_64, x86_64)
- GitHub Check: build-rust (armv7-linux-androideabi, armeabi-v7a, armv7)
- GitHub Check: build-rust (i686-linux-android, x86, i686)
- GitHub Check: build-rust (aarch64-linux-android, arm64-v8a, aarch64)
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
🔇 Additional comments (8)
.github/workflows/android-build.yml (8)
9-12: LGTM! Environment-aware API configuration.The conditional API URLs properly separate PR builds (dev endpoints) from master builds (production endpoints), which is a solid practice for testing changes in isolation.
52-71: LGTM! Well-structured matrix for parallel Android target builds.The fail-fast: false configuration ensures all targets complete even if one fails, providing comprehensive CI feedback. The inclusion of short_name and jni_dir metadata cleanly handles per-target differences.
162-168: LGTM! Correct Rust library build command.Building only the library (
--lib) for each target is appropriate for Android JNI integration. The sccache stats output is helpful for monitoring cache effectiveness.
241-254: LGTM! Correct JNI library placement with helpful verification.The native library organization matches Android's expected JNI structure. The verification output (lines 252-254) will be valuable for debugging any library placement issues.
282-289: LGTM! Efficient parallel APK and AAB generation.Building both release artifacts with
--paralleltakes advantage of the 8-core runner to reduce overall package time.
170-175: Use the explicit library name instead of wildcard for clarity.The library is configured with
name = "app_lib"andcrate-type = ["cdylib", ...], which produces exactly one.sofile:libapp_lib.so. While*.soworks correctly, explicitly naming the artifact file aslibapp_lib.sowould be clearer and more maintainable.
118-160: API level 24 is correctly aligned with minSdkVersion; NDK paths are valid.The verification confirms:
API level alignment: ✓ The minSdk in build.gradle.kts is set to 24, matching the android24 API level used consistently across all target toolchain paths.
NDK r27c and linux-x86_64 paths: ✓ Confirmed correct for GitHub Actions runners. All targets properly configured with the NDK toolchain paths.
Symlinks with sudo ln -sf: The RANLIB_* environment variables are set correctly and should be sufficient for Cargo to locate ranlib. The symlinks create names with hyphens (e.g.,
aarch64-linux-android-ranlib) while Cargo uses the RANLIB_* env vars with underscores. The symlinks may be redundant, but they provide no harm and could serve as a fallback for other build tools.
17-17: No action needed. Theubuntu-latest-8-coresrunner is a standard GitHub-hosted runner and does not require custom organization configuration. It is part of GitHub's larger hosted runners offering and is already in use across multiple workflows in this repository.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Upgrades all GitHub Actions workflows to use larger runners for faster builds. macOS jobs move to macos-latest-xlarge (M2, 5 cores, 14GB RAM) and Linux jobs to ubuntu-latest-8-cores (8 CPU, 32GB RAM, 300GB SSD).
Major Changes:
- android-build.yml - Completely restructured into a 3-job pipeline: separate frontend build, parallel Rust compilation for 4 Android ABIs (aarch64, armv7, i686, x86_64), and final Gradle packaging with artifact passing
- desktop-build.yml, mobile-build.yml, testflight-on-comment.yml - Straightforward runner upgrades for build jobs
- release.yml - All jobs upgraded to larger runners
- claude.yml - Upgraded to 8-core runner for AI automation tasks
Minor Issues:
- Some lightweight jobs (permission checks, JSON generation) use 8-core runners unnecessarily, adding cost without benefit
- PR requires manual setup of
ubuntu-latest-8-coresrunner in org settings before merging (instructions provided)
Confidence Score: 4/5
- Safe to merge after creating the ubuntu-latest-8-cores runner in org settings
- The changes are well-structured and the Android pipeline refactor is architecturally sound. Minor inefficiencies exist with oversized runners for lightweight jobs, but these won't cause failures. Main blocker is the required manual runner setup before merge.
- Verify the
ubuntu-latest-8-coresrunner is created in org settings before merging, otherwise all Linux and Android builds will fail
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 4/5 | Restructured into 3-job pipeline (frontend build, parallel Rust builds, Gradle packaging) and upgraded to 8-core runners. Architecture looks sound with proper artifact passing. |
| .github/workflows/claude.yml | 5/5 | Simple runner upgrade from ubuntu-latest to ubuntu-latest-8-cores for Claude Code automation. Appropriate for complex AI-driven tasks. |
| .github/workflows/desktop-build.yml | 5/5 | Runner upgrades to macos-latest-xlarge and ubuntu-latest-8-cores. Appropriate for Rust compilation and Tauri builds. |
| .github/workflows/mobile-build.yml | 5/5 | Runner upgrade to macos-latest-xlarge for iOS builds. Appropriate for Xcode compilation. |
| .github/workflows/release.yml | 4/5 | All jobs upgraded to larger runners. Some lightweight jobs (create-release, update-latest-json) use 8-core runners unnecessarily. |
| .github/workflows/testflight-on-comment.yml | 4/5 | Both jobs upgraded to larger runners. The check-comment job uses 8-core runner unnecessarily for permission checking. |
Sequence Diagram
sequenceDiagram
participant GH as GitHub Actions
participant BF as build-frontend Job
participant BR as build-rust Job (Matrix)
participant PA as package-android Job
participant Artifacts as GitHub Artifacts
Note over GH: Android Build Workflow (New Architecture)
GH->>BF: Start on ubuntu-latest-8-cores
BF->>BF: Setup Bun & Install Dependencies
BF->>BF: Build Frontend (bun run build)
BF->>Artifacts: Upload frontend dist
BF->>BR: Trigger 4 parallel matrix jobs
par Parallel Rust Builds (4 targets)
BR->>BR: aarch64 - Setup NDK, Build Rust lib
BR->>BR: Generate tauri.settings.gradle (aarch64 only)
BR->>Artifacts: Upload aarch64 .so + gradle file
and
BR->>BR: armv7 - Setup NDK, Build Rust lib
BR->>Artifacts: Upload armv7 .so
and
BR->>BR: i686 - Setup NDK, Build Rust lib
BR->>Artifacts: Upload i686 .so
and
BR->>BR: x86_64 - Setup NDK, Build Rust lib
BR->>Artifacts: Upload x86_64 .so
end
BR->>PA: All builds complete
PA->>Artifacts: Download frontend dist
PA->>Artifacts: Download all 4 native libraries
PA->>Artifacts: Download tauri.settings.gradle
PA->>PA: Place libraries in jniLibs directories
PA->>PA: Setup Android signing
PA->>PA: Generate tauri.properties
PA->>PA: Run Gradle (assemble + bundle)
PA->>Artifacts: Upload APK & AAB (5 day retention)
| check-comment: | ||
| if: github.event.issue.pull_request && contains(github.event.comment.body, 'testflight build') | ||
| runs-on: ubuntu-latest | ||
| runs-on: ubuntu-latest-8-cores |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary 8-core runner for lightweight permission check
| runs-on: ubuntu-latest-8-cores | |
| runs-on: ubuntu-latest |
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/testflight-on-comment.yml
Line: 15:15
Comment:
unnecessary 8-core runner for lightweight permission check
```suggestion
runs-on: ubuntu-latest
```
<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.
.github/workflows/release.yml
Outdated
| jobs: | ||
| create-release: | ||
| runs-on: ubuntu-latest | ||
| runs-on: ubuntu-latest-8-cores |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary 8-core runner for lightweight version extraction
| runs-on: ubuntu-latest-8-cores | |
| runs-on: ubuntu-latest |
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/release.yml
Line: 11:11
Comment:
unnecessary 8-core runner for lightweight version extraction
```suggestion
runs-on: ubuntu-latest
```
<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.
.github/workflows/release.yml
Outdated
| update-latest-json: | ||
| needs: build-tauri | ||
| runs-on: ubuntu-latest | ||
| runs-on: ubuntu-latest-8-cores |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary 8-core runner for lightweight artifact download and JSON generation
| runs-on: ubuntu-latest-8-cores | |
| runs-on: ubuntu-latest |
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/release.yml
Line: 325:325
Comment:
unnecessary 8-core runner for lightweight artifact download and JSON generation
```suggestion
runs-on: ubuntu-latest
```
<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.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
.github/workflows/android-build.yml (3)
180-203: Consider checking if Tauri CLI has a dedicated command for generating gradle files.The current approach runs a build that intentionally fails to generate
tauri.settings.gradle. While functional, this is fragile and wastes build time attempting Rust compilation before failing.Does Tauri CLI 2.9.2 have a command to generate Android gradle files without building?
243-251: Potential cache key issue: gradle files may not exist at cache-restore time.The Gradle cache key includes
frontend/src-tauri/gen/android/**/*.gradle*, but these files are downloaded from artifacts after the cache is restored (line 265-269). This meanshashFiles()will return an empty hash at cache-restore time, potentially causing cache misses.Consider using a cache key that doesn't depend on downloaded artifacts, such as:
key: ${{ runner.os }}-gradle-${{ hashFiles('**/Cargo.lock') }}
271-284: Add error handling for library placement.The
cpcommands with*.soglobs may fail silently if artifacts are missing. Consider adding verification after each copy or usingset -eto ensure the script exits on any error.♻️ Proposed improvement
- name: Place native libraries in jniLibs run: | + set -e # Exit on any error + # Create jniLibs directories mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86,x86_64} # Copy libraries to correct locations cp native-libs/android-lib-aarch64/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/ cp native-libs/android-lib-armv7/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/ cp native-libs/android-lib-i686/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/ cp native-libs/android-lib-x86_64/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/ + # Verify all ABIs have libraries + for abi in arm64-v8a armeabi-v7a x86 x86_64; do + if [ ! -f frontend/src-tauri/gen/android/app/src/main/jniLibs/$abi/*.so ]; then + echo "ERROR: No .so files found for ABI: $abi" + exit 1 + fi + done + # Verify echo "=== Native libraries placed ===" find frontend/src-tauri/gen/android/app/src/main/jniLibs -name "*.so" -exec ls -la {} \;
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: build-rust (aarch64-linux-android, arm64-v8a, aarch64)
- GitHub Check: build-rust (armv7-linux-androideabi, armeabi-v7a, armv7)
- GitHub Check: build-rust (x86_64-linux-android, x86_64, x86_64)
- GitHub Check: build-ios
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (9)
.github/workflows/android-build.yml (9)
9-13: LGTM: Environment configuration is correct.The conditional API URL configuration appropriately routes PRs to staging/dev environments and pushes to production endpoints.
55-77: LGTM: Matrix strategy is well-configured.The parallel build strategy with
fail-fast: falseallows all Android targets to build independently, maximizing the benefit of the 8-core runner and providing comprehensive build results even if one target fails.
86-102: LGTM: Per-target sccache configuration optimizes parallel builds.The per-target cache keys with fallbacks enable effective cache sharing while maintaining isolation, which is ideal for the parallelized matrix strategy.
162-178: LGTM: Efficient Tauri CLI installation strategy.Installing Tauri CLI only for the aarch64 job (to generate shared gradle files) avoids redundant installations across all four matrix jobs, saving build time.
205-218: LGTM: Rust library build and artifact upload are correctly configured.The per-target artifact naming strategy (
android-lib-{short_name}) facilitates clean artifact retrieval in the packaging stage.
253-269: LGTM: Artifact downloads are properly configured.The pattern-based download for native libraries (
android-lib-*) efficiently retrieves all four target libraries in a single step.
286-319: LGTM: Signing and packaging steps are correctly configured.The workflow properly handles Android app signing and builds both APK and AAB artifacts. The use of
RUNNER_TEMPfor the keystore ensures automatic cleanup.
321-333: LGTM: Final artifact uploads are properly configured.The 5-day retention for final APK and AAB artifacts (vs. 1-day for intermediate artifacts) appropriately balances storage costs with the need to access release builds.
17-17: Theubuntu-latest-8-coresrunner is a GitHub-provided label for larger hosted runners, not a custom runner requiring manual setup. It's already being used across multiple workflows in the repository (android-build.yml, release.yml, testflight-on-comment.yml, desktop-build.yml, and claude.yml), indicating the organization already has access to the larger runners feature. No additional setup or creation is needed.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Upgrades all GitHub Actions workflows to use larger runners—macos-latest-xlarge (M2, 5 cores + 8 GPU, 14GB RAM) for macOS jobs and ubuntu-latest-8-cores (8 CPU, 32GB RAM, 300GB SSD) for Linux jobs—to accelerate build times across desktop, mobile, Android, release, and automation workflows. The android-build.yml was additionally restructured into a parallel job architecture with separate stages for frontend build, Gradle file generation, parallel Rust compilation across four Android targets, and final packaging.
Confidence Score: 4/5
- Safe to merge with minor optimization opportunities identified
- The runner upgrades are straightforward infrastructure changes with no logic modifications. One potential issue was identified: the
build-rustjob in android-build.yml depends onbuild-frontendbut doesn't use the artifact, which could indicate either missing artifact download or unnecessary dependency causing sequential execution instead of parallelization. Additionally, the permission-checking job in testflight-on-comment.yml uses the 8-core runner for minimal API work, which is wasteful but not blocking. The macOSmacos-latest-xlargerunner works automatically, but the custom Ubuntu runner must be created before merge as documented. .github/workflows/android-build.ymlrequires verification that the dependency between build-rust and build-frontend is intentional
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 4/5 | Restructures Android CI to use ubuntu-latest-8-cores runners with parallel job architecture; splits builds into frontend, Gradle generation, parallel Rust targets, and packaging stages |
Sequence Diagram
sequenceDiagram
participant Trigger as Workflow Trigger
participant macOS as macos-latest-xlarge<br/>(M2, 5 cores, 14GB)
participant Linux as ubuntu-latest-8-cores<br/>(8 CPU, 32GB, 300GB SSD)
Note over Trigger,Linux: Desktop & Mobile Builds
Trigger->>macOS: "Build universal macOS app"
Trigger->>Linux: "Build Linux app"
macOS-->>Trigger: "DMG + .app artifacts"
Linux-->>Trigger: "AppImage + .deb artifacts"
Note over Trigger,Linux: Android Build (Parallel Architecture)
Trigger->>Linux: "Build frontend once"
Linux->>Linux: "Generate Gradle files"
par Parallel Rust Compilation
Linux->>Linux: "Build aarch64 target"
Linux->>Linux: "Build armv7 target"
Linux->>Linux: "Build i686 target"
Linux->>Linux: "Build x86_64 target"
end
Linux->>Linux: "Package APK + AAB"
Linux-->>Trigger: "Android artifacts"
Note over Trigger,Linux: Release Workflow
Trigger->>macOS: "Build signed macOS release"
Trigger->>Linux: "Build signed Linux release"
Trigger->>Linux: "Build signed Android release"
macOS-->>Trigger: "macOS release assets"
Linux-->>Trigger: "Linux + Android assets"
Linux->>Linux: "Generate latest.json"
| check-comment: | ||
| if: github.event.issue.pull_request && contains(github.event.comment.body, 'testflight build') | ||
| runs-on: ubuntu-latest | ||
| runs-on: ubuntu-latest-8-cores |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check-comment job uses ubuntu-latest-8-cores, which will require the custom runner to be created in the organization settings as noted in the PR description. This job performs minimal work (permission checking via GitHub API), so the 8-core runner may be overkill here—the standard ubuntu-latest would likely suffice and avoid the setup requirement for this specific job.
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/testflight-on-comment.yml
Line: 15:15
Comment:
The `check-comment` job uses `ubuntu-latest-8-cores`, which will require the custom runner to be created in the organization settings as noted in the PR description. This job performs minimal work (permission checking via GitHub API), so the 8-core runner may be overkill here—the standard `ubuntu-latest` would likely suffice and avoid the setup requirement for this specific job.
<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.| # Build each Rust target in parallel | ||
| build-rust: | ||
| runs-on: ubuntu-latest-8-cores | ||
| needs: build-frontend |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The build-rust job depends on build-frontend but doesn't download or use the frontend artifact. If the frontend build is required for the Rust build to succeed, add a download step. If not needed, consider removing the dependency to allow both jobs to run in parallel for faster execution.
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: 120:120
Comment:
The `build-rust` job depends on `build-frontend` but doesn't download or use the frontend artifact. If the frontend build is required for the Rust build to succeed, add a download step. If not needed, consider removing the dependency to allow both jobs to run in parallel for faster execution.
<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.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.github/workflows/android-build.yml (1)
120-120: Remove unnecessary dependency on build-frontend.The
build-rustjob declaresneeds: build-frontendbut never downloads or uses thefrontend-distartifact. This dependency forces sequential execution and delays the Rust builds.Consider removing this dependency to allow
build-rustandbuild-frontendto run in parallel, reducing overall CI time.♻️ Proposed fix
build-rust: runs-on: ubuntu-latest-8-cores - needs: build-frontend strategy: fail-fast: false
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Run `just rust-lint` after modifying Rust code to ensure proper formatting, compilation, and linting (runs fmt + clippy strict)
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-rust (i686-linux-android, x86, i686)
- GitHub Check: build-rust (armv7-linux-androideabi, armeabi-v7a, armv7)
- GitHub Check: build-rust (aarch64-linux-android, arm64-v8a, aarch64)
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: generate-gradle-files
- GitHub Check: build-linux
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
🔇 Additional comments (8)
.github/workflows/android-build.yml (8)
9-12: Good environment variable setup for multi-environment builds.The conditional environment variables correctly route PRs to dev endpoints and pushes to production endpoints.
184-226: Cross-compilation environment setup is comprehensive.The per-target configuration of LINKER, AR, CC, CXX, and RANLIB environment variables correctly sets up cross-compilation for each Android ABI.
160-177: Good caching strategy with per-target sccache isolation.The per-target sccache caching (using
matrix.short_name) prevents cache conflicts between different Android ABIs while the shared cargo registry cache reduces redundant downloads.
246-246: Correct job dependencies ensure artifact availability.The
package-androidjob properly depends on bothbuild-rust(which completes after all matrix targets) andgenerate-gradle-files, ensuring all required artifacts are available before packaging.
294-307: Native library placement logic is clear and verifiable.The step systematically places each target's
.sofiles into the correct JNI ABI directories and includes verification output for debugging.
335-342: Parallel Gradle build optimizes packaging time.Using
--parallelfor bothassembleUniversalReleaseandbundleUniversalReleasetakes advantage of Gradle's parallel execution capabilities to reduce packaging time.
17-17: Verify custom runner availability before merging.The workflow uses
ubuntu-latest-8-coreson lines 17, 53, 119, and 245, which is a custom GitHub-hosted runner that must be created in organization settings before merging (8 CPU, 32GB RAM, 300GB SSD, Ubuntu 22.04 or 24.04).
88-108: Consider updating Tauri CLI and investigating dedicated gradle initialization.The workflow uses Tauri CLI 2.9.2, but the latest stable version is 2.9.5 (released Nov 30, 2025). Additionally, a dedicated
tauri android initcommand exists in the Tauri CLI, though it's primarily documented for Android project initialization rather than gradle file regeneration. Verify whether this command can replace the current approach of running a build and letting it fail after gradle file generation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR upgrades all GitHub Actions workflows to use larger runners for faster builds. The changes include straightforward runner upgrades across 5 workflows, plus a major architectural refactoring of the Android build pipeline.
Key Changes:
- Runner Upgrades: All workflows now use
ubuntu-latest-8-cores(8 CPU, 32GB RAM) for Linux andmacos-latest-xlarge(12 CPU, 30GB RAM) for macOS - Android Build Refactoring: Transformed from a single monolithic job to a 4-job pipeline with parallel Rust compilation per Android ABI (aarch64, armv7, i686, x86_64)
- Artifact-based Build: Frontend, gradle files, and native libraries are now shared via GitHub artifacts between jobs
Runner Setup Clarification Needed:
The PR description instructs to "create the Ubuntu larger runner in your org settings," suggesting manual setup of an organization-hosted runner. However, ubuntu-latest-8-cores and macos-latest-xlarge are official GitHub-hosted larger runner names that work automatically on GitHub Team/Enterprise plans. Please clarify:
- Are you using GitHub-hosted larger runners (no setup needed)?
- Or creating custom organization-hosted runners with these names (setup required)?
If using GitHub-hosted larger runners, the setup instructions in the PR description are unnecessary and could cause confusion.
Confidence Score: 4/5
- This PR is safe to merge with minor clarification needed on runner setup
- The code changes are well-structured and the Android build refactoring is architecturally sound. Runner upgrades are consistent across all workflows. The main concern is ambiguity in the PR description about whether these are GitHub-hosted or organization-hosted runners, which could lead to confusion during setup. The android-build.yml has one minor inefficiency (duplicate frontend builds), but this doesn't affect correctness.
- Pay attention to
.github/workflows/android-build.ymldue to its major architectural changes and complexity
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 4/5 | Major refactoring from single job to multi-job pipeline with parallel builds. Upgraded to ubuntu-latest-8-cores. Architecture is sound but has minor workflow duplication issues. |
| .github/workflows/desktop-build.yml | 5/5 | Upgraded macOS job to macos-latest-xlarge and Linux job to ubuntu-latest-8-cores. Straightforward runner upgrades with no logic changes. |
| .github/workflows/release.yml | 5/5 | Upgraded all jobs to larger runners (macos-latest-xlarge and ubuntu-latest-8-cores). Updated platform conditionals consistently throughout. No issues found. |
Sequence Diagram
sequenceDiagram
participant Trigger as GitHub Event
participant Frontend as build-frontend
participant Gradle as generate-gradle-files
participant Rust1 as build-rust (aarch64)
participant Rust2 as build-rust (armv7)
participant Rust3 as build-rust (i686)
participant Rust4 as build-rust (x86_64)
participant Package as package-android
participant Artifacts as GitHub Artifacts
Trigger->>Frontend: Start (ubuntu-latest-8-cores)
Trigger->>Gradle: Start (ubuntu-latest-8-cores)
Note over Frontend: Install Bun deps<br/>Build frontend dist
Frontend->>Artifacts: Upload frontend-dist
Note over Gradle: Install deps & Tauri CLI<br/>Run cargo tauri android build<br/>Extract gradle files
Gradle->>Artifacts: Upload tauri-gradle-files
Frontend->>Rust1: Trigger (ubuntu-latest-8-cores)
Frontend->>Rust2: Trigger (ubuntu-latest-8-cores)
Frontend->>Rust3: Trigger (ubuntu-latest-8-cores)
Frontend->>Rust4: Trigger (ubuntu-latest-8-cores)
Note over Rust1,Rust4: Parallel Rust compilation<br/>with sccache per-target
Rust1->>Artifacts: Upload android-lib-aarch64
Rust2->>Artifacts: Upload android-lib-armv7
Rust3->>Artifacts: Upload android-lib-i686
Rust4->>Artifacts: Upload android-lib-x86_64
Rust1->>Package: Complete
Rust2->>Package: Complete
Rust3->>Package: Complete
Rust4->>Package: Complete
Gradle->>Package: Complete
Package->>Artifacts: Download frontend-dist
Package->>Artifacts: Download all android-lib-*
Package->>Artifacts: Download tauri-gradle-files
Note over Package: Place files in correct dirs<br/>Setup signing<br/>Run Gradle build
Package->>Artifacts: Upload maple-android-apk
Package->>Artifacts: Upload maple-android-aab
.github/workflows/android-build.yml
Outdated
| - name: Generate Tauri gradle files | ||
| working-directory: ./frontend | ||
| run: | | ||
| # Run tauri android build - it will generate gradle files then fail at Rust compile (expected) | ||
| cargo tauri android build 2>&1 || true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The generate-gradle-files job duplicates work by building the frontend independently, while build-frontend runs in parallel. Since Tauri's android build command internally builds the frontend before generating gradle files, this job will waste CI time rebuilding what's already built in build-frontend.
Consider making generate-gradle-files depend on build-frontend and downloading the frontend-dist artifact, or accept the duplication as a tradeoff for parallel execution speed.
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: 95:99
Comment:
The `generate-gradle-files` job duplicates work by building the frontend independently, while `build-frontend` runs in parallel. Since Tauri's android build command internally builds the frontend before generating gradle files, this job will waste CI time rebuilding what's already built in `build-frontend`.
Consider making `generate-gradle-files` depend on `build-frontend` and downloading the frontend-dist artifact, or accept the duplication as a tradeoff for parallel execution speed.
<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.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @.github/workflows/android-build.yml:
- Around line 15-50: The upload-artifact step for "Upload frontend dist"
currently may warn instead of failing when frontend/dist is missing; update that
step (the actions/upload-artifact@v4 usage named "Upload frontend dist") to
include the if-no-files-found: error option so the job fails fast if the built
artifact directory isn't present.
- Around line 243-248: The upload steps "Upload native library" and "Upload
Android AAB" currently allow missing files silently; add if-no-files-found:
error to both upload-artifact actions so the job fails fast on missing
artifacts. Also relocate the "Cache Gradle" step so it runs after the "Place
Tauri gradle files" step (ensuring the cache key hashes the populated gradle
files rather than an empty directory) to avoid sticky/incorrect cache hits; keep
the same cache key logic but compute it after the gradle files are placed.
- Around line 75-123: The cache/restore-keys and version check are too weak:
tighten the cache key and implement an explicit version check for cargo-tauri
instead of just command -v; replace the loose restore-keys prefix with a
deterministic key including the tauri-cli version (e.g.,
runner.os-cargo-bin-tauri-cli-2.9.2) or remove restore-keys, then change the
install step to run cargo-tauri --version and compare its output to the expected
"tauri-cli 2.9.2" (if it differs or command fails, run cargo install tauri-cli
--version "2.9.2" --locked --force); finally add if-no-files-found: error to the
actions/upload-artifact@v4 step to fail early when
frontend/src-tauri/gen/android files are missing.
🧹 Nitpick comments (2)
.github/workflows/android-build.yml (2)
9-12: Make the “PR vs push” endpoint selection explicit (and future-proof).
The&&/||expression works, but it’s easy to misread/extend later (e.g., addingworkflow_dispatch). Consider a tiny comment or switching to a clearer expression style to avoid accidental prod/dev flips.
124-129: Unblock parallelism: don’t gatebuild-rustonbuild-frontend; instead makepackage-androiddepend on all producers explicitly.
Right nowbuild-rustwaits onbuild-frontendeven though it doesn’t consume its artifact; it’s only enforcing ordering indirectly.Proposed needs-graph tweak
build-rust: runs-on: ubuntu-latest-8-cores - needs: build-frontend strategy: fail-fast: false @@ package-android: runs-on: ubuntu-latest-8-cores - needs: [build-rust, generate-gradle-files] + needs: [build-frontend, build-rust, generate-gradle-files]Also applies to: 250-254
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Run `just rust-lint` after modifying Rust code to ensure proper formatting, compilation, and linting (runs fmt + clippy strict)
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: build-rust (aarch64-linux-android, arm64-v8a, aarch64)
- GitHub Check: build-rust (x86_64-linux-android, x86_64, x86_64)
- GitHub Check: build-rust (armv7-linux-androideabi, armeabi-v7a, armv7)
- GitHub Check: build-rust (i686-linux-android, x86, i686)
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: generate-gradle-files
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
| # Build frontend once, shared by all jobs | ||
| build-frontend: | ||
| runs-on: ubuntu-latest-8-cores | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Java | ||
| uses: actions/setup-java@v4 | ||
| - name: Setup Bun | ||
| uses: oven-sh/setup-bun@v1 | ||
| with: | ||
| distribution: 'temurin' | ||
| java-version: '21' | ||
| bun-version: 1.2.2 | ||
|
|
||
| - name: Setup Android SDK | ||
| uses: android-actions/setup-android@v3 | ||
| - name: Cache Bun dependencies | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ~/.bun/install/cache | ||
| frontend/node_modules | ||
| key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lockb') }} | ||
| 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 | ||
|
|
||
| - name: Upload frontend dist | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: frontend-dist | ||
| path: frontend/dist | ||
| retention-days: 1 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
ubuntu-latest-8-cores GitHub Actions runner label
💡 Result:
"ubuntu-latest-8-cores" is a GitHub-hosted larger runner label that schedules your job on an Ubuntu image with 8 CPU cores (the "ubuntu – latest" image). Add it to a workflow with runs-on: ubuntu-latest-8-cores. This label is provided via GitHub's "larger runners" offering (available to customers/organizations who have the larger-runner group enabled). [1][2]
Example:
runs-on: ubuntu-latest-8-cores
Sources: GitHub changelog (larger hosted runners) and GitHub Actions docs. [1] [2]
🏁 Script executed:
# Check if there are any runner group or custom runner configurations in the repository
git ls-files | grep -E "(runner|actions)" | head -20Repository: OpenSecretCloud/Maple
Length of output: 47
🏁 Script executed:
# Look for any GitHub Actions workflow configuration files
fd -e yml -e yaml .github/workflows/ | head -20Repository: OpenSecretCloud/Maple
Length of output: 442
🏁 Script executed:
# Check other workflow files for runner usage patterns
rg "runs-on:" .github/workflows/ -A 1 -B 1Repository: OpenSecretCloud/Maple
Length of output: 2624
🌐 Web query:
actions/upload-artifact@v4 if-no-files-found parameter documentation
💡 Result:
The actions/upload-artifact@v4 input if-no-files-found controls what happens when the provided path matches no files. Valid values:
- warn (default): emit a warning but do not fail the step. [1][2]
- error: fail the step with an error. [1][2]
- ignore: suppress warnings/errors and do not fail the step. [1][2]
Example usage:
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: path/to/artifact/
if-no-files-found: error. [1]
Sources: GitHub actions/upload-artifact README and GitHub Actions docs. [1][2]
🏁 Script executed:
# Check the android-build.yml file to see full context of upload-artifact usage
cat -n .github/workflows/android-build.yml | sed -n '40,50p'Repository: OpenSecretCloud/Maple
Length of output: 415
Consider failing fast if the frontend build output is missing.
Add if-no-files-found: error to the upload-artifact step to ensure the workflow fails immediately if frontend/dist isn't generated, rather than silently warning.
Proposed change
- name: Upload frontend dist
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: frontend/dist
retention-days: 1
+ if-no-files-found: error🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 15 - 50, The
upload-artifact step for "Upload frontend dist" currently may warn instead of
failing when frontend/dist is missing; update that step (the
actions/upload-artifact@v4 usage named "Upload frontend dist") to include the
if-no-files-found: error option so the job fails fast if the built artifact
directory isn't present.
| - name: Cache Cargo bin (Tauri CLI) | ||
| uses: actions/cache@v4 | ||
| with: | ||
| targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android,i686-linux-android | ||
| path: ~/.cargo/bin/ | ||
| key: ${{ runner.os }}-cargo-bin-tauri-cli-2.9.2 | ||
| restore-keys: | | ||
| ${{ runner.os }}-cargo-bin-tauri-cli- | ||
| - name: Install frontend dependencies | ||
| working-directory: ./frontend | ||
| run: bun install | ||
|
|
||
| - name: Install Tauri CLI | ||
| run: | | ||
| if ! command -v cargo-tauri &> /dev/null; then | ||
| cargo install tauri-cli --version "2.9.2" --locked | ||
| fi | ||
| env: | ||
| CARGO_CFG_TARGET_OS: linux | ||
|
|
||
| - name: Generate Tauri gradle files | ||
| working-directory: ./frontend | ||
| run: | | ||
| # Run tauri android build - it will generate gradle files then fail at Rust compile (expected) | ||
| cargo tauri android build 2>&1 || true | ||
| # Verify the files were generated | ||
| if [ -f "src-tauri/gen/android/tauri.settings.gradle" ] && [ -f "src-tauri/gen/android/app/tauri.build.gradle.kts" ]; then | ||
| echo "=== tauri.settings.gradle ===" | ||
| cat src-tauri/gen/android/tauri.settings.gradle | ||
| echo "" | ||
| echo "=== tauri.build.gradle.kts ===" | ||
| cat src-tauri/gen/android/app/tauri.build.gradle.kts | ||
| else | ||
| echo "ERROR: Tauri gradle files were not generated" | ||
| ls -la src-tauri/gen/android/ | ||
| ls -la src-tauri/gen/android/app/ || true | ||
| exit 1 | ||
| fi | ||
| - name: Upload Tauri gradle files | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: tauri-gradle-files | ||
| path: | | ||
| frontend/src-tauri/gen/android/tauri.settings.gradle | ||
| frontend/src-tauri/gen/android/app/tauri.build.gradle.kts | ||
| retention-days: 1 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
Tauri CLI 2.9.x cargo tauri android build gradle file generation requirements Java Android SDK NDK
💡 Result:
Short answer — for Tauri CLI v2.9.x (cargo tauri android build) you need:
-
Android Studio (use its bundled JBR or a standalone JDK). Set JAVA_HOME to the JBR/JDK path. Java 17 is the recommended runtime (templates updated to Gradle 8.9/AGP 8.5.1 add Java 21 support, but Java 17 remains recommended). [1][2]
-
Android SDK components (install via Android Studio SDK Manager): Android SDK Platform(s), Platform-Tools, Build-Tools, and Command-line Tools. Configure ANDROID_HOME to your SDK path. [1]
-
Android NDK (Side-by-side). Install via SDK Manager and set NDK_HOME to the NDK folder (e.g. $ANDROID_HOME/ndk/). Tauri expects an NDK side-by-side installation. [1]
-
Rust Android targets added via rustup: aarch64-linux-android, armv7-linux-androideabi, i686-linux-android, x86_64-linux-android. [1]
-
Gradle / Android Gradle Plugin used in templates: Gradle 8.9 and AGP 8.5.1 (so use a matching Android Studio and toolchain). [2]
Notes:
- Min Android API default is 24 (Android 7.0); you can change minSdkVersion in tauri config if needed. [3]
Sources:
[1] Tauri Prerequisites — Android (official docs).
[2] Tauri CLI release notes — Gradle/AGP update (templates).
[3] Tauri Google Play / Android build notes (minSdkVersion).
🌐 Web query:
actions/cache restore-keys how does it work version mismatch risk
💡 Result:
Short answer
- restore-keys are tried only after the primary key misses, checked in the listed order, and matched by prefix (most-recent matching cache wins). [1]
- caches include a cache "version" (metadata based on the cached paths and compression/OS) so a cache created with a different compression/tool or different paths/OS will not be considered a valid match — this prevents decompress/format mismatches. [1][2]
How restore-keys matching works (behavior)
-
- Look for an exact match of key in the branch; 2) look for prefix matches of key; 3) if still none, check each restore-key in order for exact and then prefix matches; 4) if nothing in the branch, repeat the same search on the default branch. If multiple partial matches exist for a restore-key, the most-recent cache is used. The action sets outputs.cache-hit = true only for an exact key match. [1]
Version-mismatch risk
- The cache "version" stamps the archive with the compression/tool and the set of paths. If the version differs (e.g., cache created on Windows vs Linux, different compression, or different paths), the cache will be considered a different entry and won't restore — preventing decompression/incompatibility errors. However, using broad restore-keys can still restore an older cache that is functionally incompatible (stale dependencies, different toolchain versions), which can cause build or runtime failures. [1][2]
Mitigations
- Include file hashes or tool versions in your primary key (e.g., hashFiles('package-lock.json') or ${runner.os}-${{ hashFiles('...') }}). [1]
- Add explicit tool/version strings to the key (node/npm/python versions), or separate caches per OS.
- Use restore-keys only for safe, backward-compatible fallbacks (e.g., to speed installs), not for binary/compiled artifacts across major-version changes.
- Check steps.cache.outputs.cache-hit and run a fresh install or rebuild when cache-hit != 'true', or validate restored artifacts before reuse.
- Pin/update actions/cache runner compatibility (use recent actions/cache versions) to avoid service/format changes. [1][2]
Sources
[1] GitHub Docs — Dependency caching reference / Cache key matching.
[2] actions/cache repository / cache version explanation.
🌐 Web query:
cargo install force reinstall version check behavior
💡 Result:
Short answer: cargo install normally skips rebuilding if it thinks the installed package is "up‑to‑date" (it compares package version & source, installed binary names, chosen features, profile/target, etc.). Using --force makes cargo unconditionally rebuild and overwrite the installed binaries (i.e., it will reinstall even the same version). There is also an unstable install-upgrade mode that changes the up‑to‑date behavior. [1][2][3]
Sources:
- cargo install docs / man page (behavior & --force). [1][2]
- note about the unstable -Z install-upgrade behavior. [3]
Fix tauri-cli cache/version mismatch risk. Broad restore-keys prefixes can resurrect older ~/.cargo/bin/ caches, and checking only command -v cargo-tauri won't detect a stale version.
Replace the version check with an explicit version comparison:
Proposed fix
- name: Install Tauri CLI
run: |
- if ! command -v cargo-tauri &> /dev/null; then
- cargo install tauri-cli --version "2.9.2" --locked
- fi
+ set -euo pipefail
+ WANT="2.9.2"
+ HAVE="$(cargo tauri --version 2>/dev/null || true)"
+ if ! command -v cargo-tauri >/dev/null 2>&1 || ! printf '%s' "$HAVE" | grep -q "$WANT"; then
+ cargo install tauri-cli --version "$WANT" --locked --force
+ fi
env:
CARGO_CFG_TARGET_OS: linuxAlso add if-no-files-found: error to the gradle artifact upload to catch generation failures earlier:
Proposed hardening
- name: Upload Tauri gradle files
uses: actions/upload-artifact@v4
with:
name: tauri-gradle-files
path: |
frontend/src-tauri/gen/android/tauri.settings.gradle
frontend/src-tauri/gen/android/app/tauri.build.gradle.kts
retention-days: 1
+ if-no-files-found: error🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 75 - 123, The
cache/restore-keys and version check are too weak: tighten the cache key and
implement an explicit version check for cargo-tauri instead of just command -v;
replace the loose restore-keys prefix with a deterministic key including the
tauri-cli version (e.g., runner.os-cargo-bin-tauri-cli-2.9.2) or remove
restore-keys, then change the install step to run cargo-tauri --version and
compare its output to the expected "tauri-cli 2.9.2" (if it differs or command
fails, run cargo install tauri-cli --version "2.9.2" --locked --force); finally
add if-no-files-found: error to the actions/upload-artifact@v4 step to fail
early when frontend/src-tauri/gen/android files are missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR successfully upgrades GitHub Actions workflows to use larger runners for improved build performance:
Runner Upgrades:
- Linux:
ubuntu-latest→ubuntu-latest-8-cores(8 CPU, 32GB RAM) - macOS:
macos-latest→macos-latest-xlarge(M2, 5 cores + 8 GPU, 14GB RAM)
Key Changes:
-
Android Build Refactor - The most significant change is the complete restructuring of
android-build.ymlfrom a single monolithic job to 4 parallel jobs:build-frontend: Builds frontend once using Bungenerate-gradle-files: Generates Tauri Android metadatabuild-rust: Builds native libraries for 4 ABIs in parallel (aarch64, armv7, i686, x86_64)package-android: Assembles everything into APK/AAB with Gradle
This architecture significantly improves parallelization and should drastically reduce build times.
-
RustPlugin.kt Enhancement - Adds
skipRustBuildflag support to allow Gradle packaging without Rust compilation, which is essential for the new parallel workflow. -
Environment Variables - Moves
VITE_*environment variables to workflow-level scope inandroid-build.ymlfor better organization.
Setup Required:
As noted in the PR description, the ubuntu-latest-8-cores runner must be manually created in the organization's GitHub Actions settings before merging. The macos-latest-xlarge runner is available by default.
Issues Found:
- Missing
SCCACHE_DIRenvironment variable inrelease.ymlbuild-tauri job (affects Linux caching) - Implicit dependency in
android-build.ymlpackage-android job (style issue, not blocking)
Confidence Score: 4/5
- This PR is safe to merge after addressing the sccache configuration issue in release.yml
- Score reflects one logic issue (missing SCCACHE_DIR in release.yml) that should be fixed before merging, and one minor style issue (implicit dependency). The Android workflow refactor is well-designed and the RustPlugin changes are correct. The runner upgrades are straightforward. Main concern is ensuring the ubuntu-latest-8-cores runner is created before merging.
- Pay attention to .github/workflows/release.yml - the missing SCCACHE_DIR will impact Linux build caching effectiveness
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 4/5 | Major refactor: splits Android build into 4 parallel jobs (frontend, gradle generation, Rust builds per ABI, packaging). Adds top-level env vars and uses ubuntu-latest-8-cores runners. Package job has implicit dependency on build-frontend. |
| .github/workflows/release.yml | 3/5 | Upgrades all jobs to larger runners. Updates matrix platform references. Missing SCCACHE_DIR in build-tauri job for Linux (line 104-108), which could impact caching effectiveness. |
| frontend/src-tauri/gen/android/buildSrc/src/main/java/cloud/opensecret/maple/kotlin/RustPlugin.kt | 5/5 | Adds skipRustBuild flag support to allow Gradle packaging without Rust compilation. Correctly checks property in 3 different formats (String, Boolean, hasProperty). Essential for new parallel Android build workflow. |
Sequence Diagram
sequenceDiagram
participant GH as GitHub Event
participant BF as build-frontend
participant GG as generate-gradle-files
participant BR as build-rust (4x parallel)
participant PA as package-android
GH->>BF: Trigger on push/PR
GH->>GG: Trigger on push/PR
BF->>BF: Install Bun deps
BF->>BF: Build frontend
BF->>BF: Upload frontend-dist artifact
GG->>GG: Install Tauri CLI
GG->>GG: Run tauri android build (fails intentionally)
GG->>GG: Verify gradle files generated
GG->>GG: Upload tauri-android-generated artifact
BF-->>BR: Dependency (needs: build-frontend)
BR->>BR: Download frontend-dist
BR->>BR: Build Rust for aarch64/armv7/i686/x86_64
BR->>BR: Upload android-lib-* artifacts (4x)
BR-->>PA: Dependency
GG-->>PA: Dependency
PA->>PA: Download frontend-dist (implicit dep via build-rust)
PA->>PA: Download all native libraries (4x)
PA->>PA: Download gradle generated files
PA->>PA: Place files in correct locations
PA->>PA: Run Gradle with -PskipRustBuild=true
PA->>PA: Upload APK and AAB
| package-android: | ||
| runs-on: ubuntu-latest-8-cores | ||
| needs: [build-rust, generate-gradle-files] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The package-android job downloads the frontend-dist artifact (line 328) but doesn't explicitly declare build-frontend as a dependency. While this works because build-rust depends on build-frontend, creating an implicit dependency chain, it's fragile.
If someone later modifies the workflow and removes the build-rust -> build-frontend dependency, the package-android job would fail when trying to download the artifact.
Consider making the dependency explicit:
| package-android: | |
| runs-on: ubuntu-latest-8-cores | |
| needs: [build-rust, generate-gradle-files] | |
| package-android: | |
| runs-on: ubuntu-latest-8-cores | |
| needs: [build-frontend, build-rust, generate-gradle-files] |
This makes the workflow more maintainable and the dependency graph clearer.
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: 283:285
Comment:
The `package-android` job downloads the `frontend-dist` artifact (line 328) but doesn't explicitly declare `build-frontend` as a dependency. While this works because `build-rust` depends on `build-frontend`, creating an implicit dependency chain, it's fragile.
If someone later modifies the workflow and removes the `build-rust -> build-frontend` dependency, the `package-android` job would fail when trying to download the artifact.
Consider making the dependency explicit:
```suggestion
package-android:
runs-on: ubuntu-latest-8-cores
needs: [build-frontend, build-rust, generate-gradle-files]
```
This makes the workflow more maintainable and the dependency graph clearer.
<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.
Additional Comments (1)
The cache path is set conditionally on line 84 to use Compare with:
Note: macOS doesn't need this because sccache defaults to Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/release.yml
Line: 104:108
Comment:
The "Configure sccache" step is missing the `SCCACHE_DIR` environment variable for Linux builds. This is inconsistent with other workflows and could impact caching effectiveness.
The cache path is set conditionally on line 84 to use `~/.cache/sccache` for Linux, but sccache on Linux needs `SCCACHE_DIR` to be explicitly set to use this path. Without it, sccache may use a different default location, causing cache misses.
Compare with:
- `build-android` job in this file (line 262) which correctly sets `SCCACHE_DIR`
- `desktop-build.yml` Linux job (line 180-183) which sets `SCCACHE_DIR`
- `android-build.yml` all jobs which set `SCCACHE_DIR`
```suggestion
- name: Configure sccache
run: |
echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV
echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV
```
Note: macOS doesn't need this because sccache defaults to `~/Library/Caches/Mozilla.sccache` on macOS, but we could add it conditionally if needed for clarity.
How can I resolve this? If you propose a fix, please make it concise. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/android-build.yml (1)
368-379: Gate signing and Release builds topushevents only, or build unsigned Debug on PRs.The
package-androidjob runs on bothpushandpull_request(lines 3-7) without conditionals. The "Setup Android signing" step (lines 368-379) references secrets that are unavailable on fork PRs, causing the Release build (assembleUniversalRelease bundleUniversalRelease) to fail. External contributor PRs cannot access repository secrets, so this will consistently fail on forks.This also applies to lines 394-402.
🤖 Fix all issues with AI agents
In @.github/workflows/android-build.yml:
- Around line 315-324: The cache key currently uses
hashFiles('frontend/src-tauri/gen/android/**/*.gradle*',
'frontend/src-tauri/gen/android/gradle-wrapper.properties') which can be empty
because generated Gradle files are produced later; change the key to rely only
on stable inputs (e.g., the gradle wrapper properties and any checked-in
lockfiles) and remove the generated globs from hashFiles so the key is stable on
first run—update the actions/cache step (the "Cache Gradle" job using
actions/cache@v4) to compute key from runner.os plus a hash of stable files like
gradle-wrapper.properties and repository lockfiles (or fall back to
runner.os-gradle- as needed) and keep restore-keys as-is.
- Around line 275-280: The upload step "Upload native library" currently uses
actions/upload-artifact@v4 with a glob that can match nothing and silently
continue; update the step to fail fast by adding the with key if-no-files-found
set to "error" (i.e., set if-no-files-found: error) so the job fails immediately
when frontend/src-tauri/target/${{ matrix.target }}/release/*.so is missing,
making root cause visible during CI.
- Around line 9-12: The environment variables VITE_OPEN_SECRET_API_URL and
VITE_MAPLE_BILLING_API_URL currently switch based on github.event_name ==
'pull_request', which may mis-route builds for pushes, workflow_dispatch, or
other events; either move these values to GitHub repository/environment
variables (recommended) or change the conditional to explicitly detect the
production branch (e.g., check github.ref == 'refs/heads/master' or a dedicated
prod branch) and handle workflow_dispatch/other events explicitly so that
VITE_OPEN_SECRET_API_URL and VITE_MAPLE_BILLING_API_URL resolve to the intended
prod or dev endpoints consistently.
- Around line 72-115: The step "Generate Tauri Android files" currently runs
"cargo tauri android build 2>&1 || true" which hides all failures; change it to
capture the command exit code (e.g., run "cargo tauri android build 2>&1;
build_exit=$?"), then verify the REQUIRED_FILES array (refer to REQUIRED_FILES
and the four generated paths) and only tolerate a non-zero build exit code if
all REQUIRED_FILES exist; otherwise fail with the original build exit code (or
exit 1) so genuine CLI/config errors are not swallowed.
- Around line 191-207: Replace the manual "Install sccache" run step with the
official action by using mozilla-actions/sccache-action@v0.0.9 and pass version:
"0.8.2" (remove the curl/tar/mv/chmod sequence), keep or adapt the existing
"Cache sccache" step as needed for ~/.cache/sccache, and ensure downstream build
steps set the environment variables SCCACHE_GHA_ENABLED: "true" and
RUSTC_WRAPPER: "sccache" so the action enables sccache as the rustc wrapper.
🧹 Nitpick comments (3)
.github/workflows/android-build.yml (3)
16-50: Frontend build looks solid; consider making installs deterministic.
bun installin CI is usually safer with--frozen-lockfile(prevents surprise lock changes / resolution drift).Proposed diff
- name: Install frontend dependencies working-directory: ./frontend - run: bun install + run: bun install --frozen-lockfile
75-94: Caching all of~/.cargo/binis broader than needed (can interact oddly with other Cargo-installed tools).
Since you only need thecargo-taurishim, caching just that binary is typically enough.Proposed diff
- name: Cache Cargo bin (Tauri CLI) uses: actions/cache@v4 with: - path: ~/.cargo/bin/ + path: ~/.cargo/bin/cargo-tauri key: ${{ runner.os }}-cargo-bin-tauri-cli-2.9.2 restore-keys: | ${{ runner.os }}-cargo-bin-tauri-cli-
208-217: Matrix cache contention: all 4 Rust jobs try to save the same Cargo registry cache key.
This often produces “cache already exists” noise and reduces cache usefulness. Consider making the key per-target, or use restore-only in matrix jobs and save once in a single job.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
frontend/src-tauri/gen/android/buildSrc/src/main/java/cloud/opensecret/maple/kotlin/RustPlugin.ktis excluded by!**/gen/**
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Run `just rust-lint` after modifying Rust code to ensure proper formatting, compilation, and linting (runs fmt + clippy strict)
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: generate-gradle-files
- GitHub Check: build-frontend
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-linux
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
.github/workflows/android-build.yml (1)
17-17: Theubuntu-latest-8-coresrunner label syntax is correct per GitHub Actions documentation. This is a valid, built-in label for GitHub-hosted larger runners (8-core Ubuntu) and requires no syntax changes. Ensure your organization has a paid GitHub Actions plan with larger runners provisioned; otherwise, jobs will fail due to runner unavailability rather than label syntax errors.Likely an incorrect or invalid review comment.
| - name: Install sccache | ||
| run: | | ||
| SCCACHE_VERSION=0.8.2 | ||
| SCCACHE_URL="https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz" | ||
| curl -L "$SCCACHE_URL" | tar xz | ||
| sudo mv sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl/sccache /usr/local/bin/ | ||
| chmod +x /usr/local/bin/sccache | ||
| sccache --version | ||
| - name: Cache sccache | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ~/.cache/sccache | ||
| key: ${{ runner.os }}-sccache-android-${{ hashFiles('**/Cargo.lock') }} | ||
| key: ${{ runner.os }}-sccache-android-${{ matrix.short_name }}-${{ hashFiles('**/Cargo.lock') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-sccache-android-${{ matrix.short_name }}- | ||
| ${{ runner.os }}-sccache-android- | ||
| ${{ runner.os }}-sccache- | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
mozilla sccache official GitHub Action installation
💡 Result:
Short answer — use the Mozilla Actions sccache-action. Example installation and usage:
-
Add the action step to your workflow (replace version as desired):
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.9
with:
version: "v0.10.0" # optional — >= v0.10.0 recommended
- name: Run sccache-cache
-
Enable sccache for Rust (set env in the job/step):
env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache" -
For C/C++ set SCCACHE_GHA_ENABLED and configure compiler launchers:
env:
SCCACHE_GHA_ENABLED: "true"
and pass to CMake:
-DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
or to configure:
CC="sccache gcc" CXX="sccache gcc" (or clang) -
On GHES provide a token via input if needed:
with:
token: ${{ secrets.MY_GITHUB_TOKEN }}
Sources: Mozilla-Actions sccache-action README and GitHub Marketplace listing. [1][2]
References
[1] mozilla-actions/sccache-action README.
[2] sccache Action — GitHub Marketplace.
🌐 Web query:
sccache release checksum verification GitHub Actions
💡 Result:
Yes — sccache releases on GitHub publish per-asset SHA256 lines (files named *.sha256). You can download the release asset and its .sha256, extract the hex hash, and verify with sha256sum in a GitHub Actions step.
Example (replace URLs with the release asset URL and its .sha256):
- download asset and checksum
- curl -L -o sccache.tar.gz "<ASSET_URL>"
- curl -L -o sccache.tar.gz.sha256 "<ASSET_URL>.sha256"
- extract 64‑char hash and verify against the downloaded file
- HASH=$(grep -oE '[a-f0-9]{64}' sccache.tar.gz.sha256)
- echo "$HASH sccache.tar.gz" > sum.txt
- sha256sum --check sum.txt
GitHub Actions step example:
- name: Download and verify sccache
run: |
curl -L -o sccache.tar.gz "<ASSET_URL>"
curl -L -o sccache.tar.gz.sha256 "<ASSET_URL>.sha256"
HASH=$(grep -oE '[a-f0-9]{64}' sccache.tar.gz.sha256)
echo "$HASH sccache.tar.gz" > sum.txt
sha256sum --check sum.txt
References: sccache releases (example shows .sha256 files and their contents). [1]
If you prefer using the official sccache Action for installation, see its repo/usage. [2]
Sources:
[1] mozilla/sccache releases (assets include .sha256 files).
[2] Mozilla-Actions/sccache-action (GitHub Action usage).
🏁 Script executed:
# Check if there are other sccache installations in the repository
rg -i "sccache" --type yamlRepository: OpenSecretCloud/Maple
Length of output: 47
🏁 Script executed:
# Search more broadly for sccache references
rg "sccache" -iRepository: OpenSecretCloud/Maple
Length of output: 47
🏁 Script executed:
# Also check the specific file to understand the context
cat -n .github/workflows/android-build.yml | sed -n '180,220p'Repository: OpenSecretCloud/Maple
Length of output: 1773
Use the official mozilla-actions/sccache-action instead of manual download.
The current implementation downloads sccache v0.8.2 without integrity verification, creating a supply-chain risk. Mozilla maintains an official GitHub Action that handles installation securely; replace this step with:
- name: Install sccache
uses: mozilla-actions/sccache-action@v0.0.9
with:
version: "0.8.2"Then configure the environment variables (SCCACHE_GHA_ENABLED: "true" and RUSTC_WRAPPER: "sccache") for the build steps that follow.
🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 191 - 207, Replace the
manual "Install sccache" run step with the official action by using
mozilla-actions/sccache-action@v0.0.9 and pass version: "0.8.2" (remove the
curl/tar/mv/chmod sequence), keep or adapt the existing "Cache sccache" step as
needed for ~/.cache/sccache, and ensure downstream build steps set the
environment variables SCCACHE_GHA_ENABLED: "true" and RUSTC_WRAPPER: "sccache"
so the action enables sccache as the rustc wrapper.
| - name: Upload native library | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: android-lib-${{ matrix.short_name }} | ||
| path: frontend/src-tauri/target/${{ matrix.target }}/release/*.so | ||
| retention-days: 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fail fast if .so artifacts are missing.
upload-artifact can warn and continue if the glob matches nothing; failing here makes root cause clearer than later cp errors in packaging.
Proposed diff
- name: Upload native library
uses: actions/upload-artifact@v4
with:
name: android-lib-${{ matrix.short_name }}
path: frontend/src-tauri/target/${{ matrix.target }}/release/*.so
+ if-no-files-found: error
retention-days: 1📝 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.
| - name: Upload native library | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: android-lib-${{ matrix.short_name }} | |
| path: frontend/src-tauri/target/${{ matrix.target }}/release/*.so | |
| retention-days: 1 | |
| - name: Upload native library | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: android-lib-${{ matrix.short_name }} | |
| path: frontend/src-tauri/target/${{ matrix.target }}/release/*.so | |
| if-no-files-found: error | |
| retention-days: 1 |
🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 275 - 280, The upload step
"Upload native library" currently uses actions/upload-artifact@v4 with a glob
that can match nothing and silently continue; update the step to fail fast by
adding the with key if-no-files-found set to "error" (i.e., set
if-no-files-found: error) so the job fails immediately when
frontend/src-tauri/target/${{ matrix.target }}/release/*.so is missing, making
root cause visible during CI.
| - 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- | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gradle cache key likely hashes files that don’t exist yet in this job.
Because generated Gradle files are only placed later (after artifact download), hashFiles(...) here may be empty/unstable. Consider keying off stable inputs (e.g., wrapper properties + lockfiles) instead.
🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 315 - 324, The cache key
currently uses hashFiles('frontend/src-tauri/gen/android/**/*.gradle*',
'frontend/src-tauri/gen/android/gradle-wrapper.properties') which can be empty
because generated Gradle files are produced later; change the key to rely only
on stable inputs (e.g., the gradle wrapper properties and any checked-in
lockfiles) and remove the generated globs from hashFiles so the key is stable on
first run—update the actions/cache step (the "Cache Gradle" job using
actions/cache@v4) to compute key from runner.os plus a hash of stable files like
gradle-wrapper.properties and repository lockfiles (or fall back to
runner.os-gradle- as needed) and keep restore-keys as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR refactors the CI/CD pipeline to use larger GitHub-hosted runners and restructures the Android build into a multi-stage pipeline for improved performance.
Key Changes
Runner Upgrades (All Workflows)
- Linux:
ubuntu-latest→ubuntu-latest-8-cores(2 CPU → 8 CPU, 7GB → 32GB RAM) - macOS:
macos-latest→macos-latest-xlarge(3-core M1 → 5-core M2 + 8 GPU, 7GB → 14GB RAM)
Android Build Pipeline Refactor (android-build.yml)
The monolithic Android build job has been split into 4 stages:
- build-frontend: Builds frontend once with Bun, uploads
frontend-distartifact - generate-gradle-files: Runs
cargo tauri android init --cito generate Gradle configuration and Kotlin sources (runs parallel with stage 3) - build-rust: Matrix job building 4 Android ABIs in parallel (aarch64, armv7, i686, x86_64), each with dedicated sccache
- package-android: Assembles artifacts, runs Gradle with
-PskipRustBuild=trueto create APK/AAB
Supporting Changes
- Added top-level environment variables in
android-build.ymlfor API endpoints and client ID - Modified
RustPlugin.ktto supportskipRustBuildflag, allowing Gradle to skip Rust compilation when native libs are pre-built - Consistent runner upgrades across all 6 workflows
Architecture Benefits
The refactored Android pipeline enables:
- Parallel Rust compilation: 4 ABIs build simultaneously instead of sequentially
- Improved caching: Each ABI has its own sccache scope
- Faster iteration: Frontend builds once and is reused across all Rust builds
- Build separation: Gradle packaging decoupled from Rust compilation
The new pipeline leverages the 8-core Linux runners effectively by parallelizing the most expensive operations (Rust cross-compilation for 4 targets).
Confidence Score: 2/5
- NOT safe to merge - contains a critical path handling bug that will cause build failures
- There is a [P0] blocking issue in the artifact placement logic in android-build.yml. The
cp -R tauri-android-generated/. frontend/src-tauri/gen/android/command will create nested duplicate paths because upload-artifact@v4 preserves full paths. This will cause the package-android job to fail when it tries to find files in the wrong locations. The runner upgrades themselves are fine, but this critical bug prevents the Android build from working. - .github/workflows/android-build.yml requires immediate fix to artifact placement logic (line 348)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 4/5 | Major refactor: split single job into 4-stage pipeline (frontend build, gradle generation, parallel Rust builds per ABI, packaging). Uses ubuntu-latest-8-cores runners and new skipRustBuild flag. |
| .github/workflows/claude.yml | 5/5 | Runner upgrade: ubuntu-latest → ubuntu-latest-8-cores |
| .github/workflows/desktop-build.yml | 5/5 | Runner upgrades: macos-latest → macos-latest-xlarge, ubuntu-latest → ubuntu-latest-8-cores |
| .github/workflows/mobile-build.yml | 5/5 | Runner upgrade: macos-latest → macos-latest-xlarge for iOS builds |
| .github/workflows/release.yml | 4/5 | Runner upgrades across all jobs: macos-latest → macos-latest-xlarge, ubuntu-latest → ubuntu-latest-8-cores. Missing SCCACHE_DIR on Linux builds (noted in existing comment). |
| .github/workflows/testflight-on-comment.yml | 5/5 | Runner upgrades: ubuntu-latest → ubuntu-latest-8-cores, macos-latest → macos-latest-xlarge |
| frontend/src-tauri/gen/android/buildSrc/src/main/java/cloud/opensecret/maple/kotlin/RustPlugin.kt | 5/5 | Added skipRustBuild flag detection to skip Rust build tasks when -PskipRustBuild is passed, enabling pre-built native libs workflow. |
Sequence Diagram
sequenceDiagram
participant GH as GitHub Actions
participant FE as build-frontend
participant GEN as generate-gradle-files
participant BR1 as build-rust (aarch64)
participant BR2 as build-rust (armv7)
participant BR3 as build-rust (i686)
participant BR4 as build-rust (x86_64)
participant PKG as package-android
GH->>FE: Trigger (ubuntu-latest-8-cores)
GH->>GEN: Trigger (ubuntu-latest-8-cores)
FE->>FE: Setup Bun, install deps
FE->>FE: Build frontend (bun run build)
FE->>GH: Upload frontend-dist artifact
par Generate Gradle files
GEN->>GEN: Install Rust & Tauri CLI
GEN->>GEN: cargo fetch (get deps)
GEN->>GEN: cargo tauri android init --ci
GEN->>GEN: Verify generated files
GEN->>GH: Upload tauri-android-generated artifact
end
GH->>BR1: Trigger after build-frontend
GH->>BR2: Trigger after build-frontend
GH->>BR3: Trigger after build-frontend
GH->>BR4: Trigger after build-frontend
par Parallel Rust builds (4 ABIs)
BR1->>GH: Download frontend-dist
BR1->>BR1: Setup NDK, sccache, toolchain
BR1->>BR1: cargo build --target aarch64-linux-android
BR1->>GH: Upload android-lib-aarch64
BR2->>GH: Download frontend-dist
BR2->>BR2: Setup NDK, sccache, toolchain
BR2->>BR2: cargo build --target armv7-linux-androideabi
BR2->>GH: Upload android-lib-armv7
BR3->>GH: Download frontend-dist
BR3->>BR3: Setup NDK, sccache, toolchain
BR3->>BR3: cargo build --target i686-linux-android
BR3->>GH: Upload android-lib-i686
BR4->>GH: Download frontend-dist
BR4->>BR4: Setup NDK, sccache, toolchain
BR4->>BR4: cargo build --target x86_64-linux-android
BR4->>GH: Upload android-lib-x86_64
end
GH->>PKG: Trigger after build-rust & generate-gradle-files
PKG->>GH: Download frontend-dist
PKG->>GH: Download all android-lib-* (pattern)
PKG->>GH: Download tauri-android-generated
PKG->>PKG: Place generated files (cp -R)
PKG->>PKG: Place .so files in jniLibs
PKG->>PKG: Setup Android signing
PKG->>PKG: Generate tauri.properties
PKG->>PKG: ./gradlew assembleUniversalRelease bundleUniversalRelease -PskipRustBuild
PKG->>GH: Upload maple-android-apk
PKG->>GH: Upload maple-android-aab
| - name: Place Tauri Android generated files | ||
| run: | | ||
| # Copy generated files into the checked out Android project | ||
| cp -R tauri-android-generated/. frontend/src-tauri/gen/android/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P0] The artifact placement will create nested duplicate paths. When uploading artifacts with actions/upload-artifact@v4, the full paths are preserved (e.g., frontend/src-tauri/gen/android/tauri.settings.gradle). After downloading to tauri-android-generated, the structure becomes tauri-android-generated/frontend/src-tauri/gen/android/.... Copying with cp -R tauri-android-generated/. frontend/src-tauri/gen/android/ creates frontend/src-tauri/gen/android/frontend/src-tauri/gen/android/... (nested duplicate). Fix: cp -R tauri-android-generated/frontend/src-tauri/gen/android/. frontend/src-tauri/gen/android/
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 345:348
Comment:
[P0] The artifact placement will create nested duplicate paths. When uploading artifacts with `actions/upload-artifact@v4`, the full paths are preserved (e.g., `frontend/src-tauri/gen/android/tauri.settings.gradle`). After downloading to `tauri-android-generated`, the structure becomes `tauri-android-generated/frontend/src-tauri/gen/android/...`. Copying with `cp -R tauri-android-generated/. frontend/src-tauri/gen/android/` creates `frontend/src-tauri/gen/android/frontend/src-tauri/gen/android/...` (nested duplicate). Fix: `cp -R tauri-android-generated/frontend/src-tauri/gen/android/. frontend/src-tauri/gen/android/`
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.github/workflows/android-build.yml:
- Around line 317-325: The Cache Gradle step's key uses hashFiles(...) against
generated Gradle files (the key expression after "key:"), which are created at
runtime and may be missing; replace that hashFiles(...) call with a hash of a
stable source like Cargo.lock (e.g., use hashFiles('Cargo.lock')) so the Gradle
cache key is stable and driven by actual dependency changes.
- Around line 219-267: The workflow redundantly creates filesystem symlinks for
ranlib (the multiple sudo ln -sf lines) despite already exporting RANLIB_*
environment variables (e.g., RANLIB_aarch64_linux_android,
RANLIB_armv7_linux_androideabi, RANLIB_i686_linux_android,
RANLIB_x86_64_linux_android); remove all sudo ln -sf ... llvm-ranlib
/usr/local/bin/... and /usr/bin/... lines from the Configure build environment
case branches and keep only the echo lines that set the CARGO_TARGET_* and
RANLIB_* environment variables so Cargo uses the configured ranlib paths.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Handle errors with `anyhow` crate or explicit Result types in Rust code
Applied to files:
.github/workflows/android-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Run `just rust-lint` after modifying Rust code to ensure proper formatting, compilation, and linting (runs fmt + clippy strict)
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-frontend
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-linux
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
🔇 Additional comments (13)
.github/workflows/android-build.yml (13)
92-95: Good defensive programming with cargo fetch before android init.Running
cargo fetch --lockedbeforecargo tauri android initensures all Tauri plugin crates are available in the registry, which prevents potential failures during the generation oftauri.settings.gradle. The--ciand--forceflags are appropriate for CI environments.
97-131: Excellent validation and debugging output for generated files.The comprehensive validation of required generated files (Gradle files, Kotlin sources, ProGuard rules) with detailed error messages and debugging output significantly improves troubleshooting. This is particularly valuable for a complex code generation step that could fail silently.
146-165: Well-structured matrix strategy for parallel Android target builds.The matrix configuration correctly maps each Android target to its corresponding JNI directory and provides a short name for cache keys. Using
fail-fast: falseensures all targets complete even if one fails, which is appropriate for CI visibility.
195-202: Good: Per-target sccache with fallback cache keys.The sccache cache configuration correctly uses target-specific keys (
android-${{ matrix.short_name }}) with appropriate fallback restore keys. This allows cache sharing across targets while maintaining target-specific caches.
345-354: Good artifact placement with verification.The script correctly copies generated Tauri files from the downloaded artifact into the Android project structure and verifies that key files exist. This provides good visibility into the artifact handoff.
355-368: Verify native library artifact names match matrix short_name.The script assumes specific artifact names (
android-lib-aarch64,android-lib-armv7, etc.) that must exactly match the names used in the build-rust job's upload step (line 280). Any mismatch will cause the copy commands to fail.The artifact names correctly match the matrix
short_namevalues, ensuring proper artifact handoff across jobs.
396-403: Good: Parallel Gradle build with skip Rust flag.Using
--parallelfor Gradle and-PskipRustBuild=trueis correct since the Rust libraries were already built in the previous job. This prevents Gradle from attempting to rebuild Rust code.
14-417: Excellent refactoring: Multi-stage pipeline with parallelization.The refactored workflow structure provides several benefits:
- Parallelization: Frontend builds once, then
generate-gradle-filesandbuild-rust(matrix) run in parallel, maximizing the use of the 8-core runner.- Clear separation of concerns: Each job has a single responsibility (build frontend, generate files, compile Rust, package).
- Artifact-based communication: Clean handoff of build artifacts between jobs reduces coupling and improves maintainability.
- Fail-fast disabled on matrix: Allows all Android targets to complete even if one fails, providing complete CI visibility.
This is a well-designed CI pipeline that should significantly speed up Android builds.
49-49: Appropriate artifact retention policies.The workflow uses:
retention-days: 1for intermediate artifacts (frontend-dist, tauri-android-generated, android-lib-*)retention-days: 5for final outputs (APK, AAB)This balances storage costs with the need to keep intermediate artifacts for debugging failed builds and preserving final outputs for distribution.
Also applies to: 144-144, 282-282, 410-410, 417-417
17-17: The runnerubuntu-latest-8-coresis already in use across multiple existing workflows (testflight-on-comment.yml, release.yml, desktop-build.yml, claude.yml) and therefore already exists in the organization's settings. No action is needed to create it for this workflow.Likely an incorrect or invalid review comment.
9-12: Environment variables are correctly propagated by default.Top-level
envvariables in GitHub Actions workflows are automatically inherited by all jobs—no explicit propagation is needed. The frontend build step (bun run build) executes with access toVITE_OPEN_SECRET_API_URL,VITE_MAPLE_BILLING_API_URL, andVITE_CLIENT_ID, and the frontend code correctly accesses them via the standard Vite pattern (import.meta.env.VITE_*). The workflow is properly configured.
269-272: Building only--libis correct for Tauri Android.Tauri's Android build process expects pre-built native Rust libraries (.so files) to be compiled separately and then provided to Gradle for packaging into the APK. The
cargo build --release --target ${{ matrix.target }} --libcommand correctly produces these JNI libraries. Ensure that the Rust crate in./frontend/src-taurihascrate-type = ["cdylib"]configured in itsCargo.tomlfor proper JNI library generation, and that the resulting .so files are copied to the correct Gradle source directory (e.g.,android/app/src/main/jniLibs/<ABI>/).
51-53: No changes needed. Thegenerate-gradle-filesjob does not require the frontend dist artifact. Thecargo tauri android initcommand generates only Android project structure and Gradle configuration files; it does not need built frontend assets. ThefrontendDistconfig setting is consumed during app packaging, not during initialization.
| - name: Configure build environment | ||
| run: | | ||
| echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV | ||
| echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV | ||
| echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV | ||
| NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }} | ||
| # Set up cross-compilation environment for this target (CC, AR, RANLIB, and LINKER) | ||
| case "${{ matrix.target }}" in | ||
| aarch64-linux-android) | ||
| echo "CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang" >> $GITHUB_ENV | ||
| echo "AR_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV | ||
| echo "CC_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang" >> $GITHUB_ENV | ||
| echo "CXX_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++" >> $GITHUB_ENV | ||
| echo "RANLIB_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" >> $GITHUB_ENV | ||
| 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/bin/aarch64-linux-android-ranlib | ||
| ;; | ||
| armv7-linux-androideabi) | ||
| echo "CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang" >> $GITHUB_ENV | ||
| echo "AR_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV | ||
| echo "CC_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang" >> $GITHUB_ENV | ||
| echo "CXX_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang++" >> $GITHUB_ENV | ||
| echo "RANLIB_armv7_linux_androideabi=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" >> $GITHUB_ENV | ||
| 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/arm-linux-androideabi-ranlib | ||
| sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/bin/armv7a-linux-androideabi-ranlib | ||
| sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/bin/arm-linux-androideabi-ranlib | ||
| ;; | ||
| i686-linux-android) | ||
| echo "CARGO_TARGET_I686_LINUX_ANDROID_LINKER=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang" >> $GITHUB_ENV | ||
| echo "AR_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV | ||
| echo "CC_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang" >> $GITHUB_ENV | ||
| echo "CXX_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang++" >> $GITHUB_ENV | ||
| echo "RANLIB_i686_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" >> $GITHUB_ENV | ||
| sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/local/bin/i686-linux-android-ranlib | ||
| sudo ln -sf $NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib /usr/bin/i686-linux-android-ranlib | ||
| ;; | ||
| x86_64-linux-android) | ||
| echo "CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang" >> $GITHUB_ENV | ||
| echo "AR_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> $GITHUB_ENV | ||
| echo "CC_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang" >> $GITHUB_ENV | ||
| echo "CXX_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++" >> $GITHUB_ENV | ||
| echo "RANLIB_x86_64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" >> $GITHUB_ENV | ||
| 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/bin/x86_64-linux-android-ranlib | ||
| ;; | ||
| esac |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, understand the repo structure
echo "=== Repository Structure ==="
git ls-files | head -20
echo ""
echo "=== Frontend/Tauri directory structure ==="
fd -type d "src-tauri|frontend" | head -10Repository: OpenSecretCloud/Maple
Length of output: 844
🏁 Script executed:
#!/bin/bash
# Run the verification script to check for hardcoded ranlib references
echo "=== Searching for ranlib references in build scripts ==="
fd -e rs -e toml -e sh | xargs grep -l -i "ranlib" 2>/dev/null || echo "No ranlib references found"
echo ""
echo "=== Checking for .cargo/config.toml ==="
find . -name ".cargo" -type d 2>/dev/null | head -5
echo ""
echo "=== Cargo config files ==="
find . -path "*/.cargo/config*" 2>/dev/nullRepository: OpenSecretCloud/Maple
Length of output: 217
🏁 Script executed:
#!/bin/bash
# Let's look at the actual workflow file to understand context
echo "=== Android build workflow file context ==="
if [ -f ".github/workflows/android-build.yml" ]; then
wc -l ".github/workflows/android-build.yml"
echo ""
echo "=== Lines around the ranlib configuration (lines 200-270) ==="
sed -n '200,270p' ".github/workflows/android-build.yml" | cat -n
fiRepository: OpenSecretCloud/Maple
Length of output: 6155
🏁 Script executed:
#!/bin/bash
# Search more comprehensively for build scripts and native dependencies
echo "=== Searching for build.rs files ==="
find . -name "build.rs" -type f 2>/dev/null
echo ""
echo "=== Searching for any Cargo.toml files ==="
find . -name "Cargo.toml" -type f 2>/dev/null | head -10
echo ""
echo "=== Check if frontend/src-tauri exists ==="
ls -la frontend/ 2>/dev/null || echo "No frontend directory"
ls -la src-tauri/ 2>/dev/null || echo "No src-tauri directory"Repository: OpenSecretCloud/Maple
Length of output: 1833
🏁 Script executed:
#!/bin/bash
# Search for any reference to tool names in the entire codebase
echo "=== Searching for any hardcoded tool paths (ar, clang, etc.) ==="
grep -r "aarch64-linux-android\|armv7a-linux-android\|i686-linux-android\|x86_64-linux-android" . --include="*.rs" --include="*.toml" --include="*.sh" 2>/dev/null | grep -v ".git" | head -20
echo ""
echo "=== Git history of android-build.yml ==="
git log --oneline .github/workflows/android-build.yml 2>/dev/null | head -10
echo ""
echo "=== Check when these symlinks were added ==="
git log -p --all -- ".github/workflows/android-build.yml" 2>/dev/null | grep -A 5 -B 5 "ranlib" | head -40Repository: OpenSecretCloud/Maple
Length of output: 279
🏁 Script executed:
#!/bin/bash
# Check the actual Cargo.toml in src-tauri if it exists
echo "=== Looking for all Rust project files ==="
find . -type f -name "Cargo.toml" 2>/dev/null
echo ""
echo "=== Check if there are references to native-build or build scripts ==="
find . -type f \( -name "Cargo.toml" -o -name "build.rs" \) 2>/dev/null -exec echo "File: {}" \; -exec head -30 {} \;Repository: OpenSecretCloud/Maple
Length of output: 1148
🏁 Script executed:
#!/bin/bash
# Let's check if there are any comments or documentation about why these symlinks exist
echo "=== Check for any Tauri-specific documentation ==="
find . -name "*.md" -type f 2>/dev/null | xargs grep -l "ranlib\|NDK\|symlink" 2>/dev/null
echo ""
echo "=== Check if there's a .cargo directory created at runtime ==="
find . -path "*/.cargo" -type d 2>/dev/null
echo ""
echo "=== Check Tauri version and Android specific config ==="
grep -i "tauri" ./frontend/src-tauri/Cargo.tomlRepository: OpenSecretCloud/Maple
Length of output: 715
🏁 Script executed:
#!/bin/bash
# Check the Android platform analysis document for relevant information
echo "=== Android platform checks analysis ==="
cat ./docs/android-platform-checks-analysis.md | head -100Repository: OpenSecretCloud/Maple
Length of output: 4243
Remove unnecessary ranlib symlink workarounds.
The configuration sets RANLIB_* environment variables for each Android target (aarch64, armv7, i686, x86_64), which is the standard approach for Cargo cross-compilation. The subsequent sudo ln -sf commands creating symlinks in /usr/local/bin and /usr/bin are redundant—the Cargo toolchain respects the environment variables without requiring filesystem symlinks.
No code in the repository (including the minimal build.rs which only calls tauri_build::build()) references these tool names by path. This pattern appears to be a conservative holdover from Tauri's android init scaffold.
Simplify by removing all sudo ln -sf commands and rely solely on the RANLIB_* environment variables already being set.
🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 219 - 267, The workflow
redundantly creates filesystem symlinks for ranlib (the multiple sudo ln -sf
lines) despite already exporting RANLIB_* environment variables (e.g.,
RANLIB_aarch64_linux_android, RANLIB_armv7_linux_androideabi,
RANLIB_i686_linux_android, RANLIB_x86_64_linux_android); remove all sudo ln -sf
... llvm-ranlib /usr/local/bin/... and /usr/bin/... lines from the Configure
build environment case branches and keep only the echo lines that set the
CARGO_TARGET_* and RANLIB_* environment variables so Cargo uses the configured
ranlib paths.
| - 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- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gradle cache key may not work correctly for generated files.
The Gradle cache key includes paths like frontend/src-tauri/gen/android/**/*.gradle*, but these files are generated in the generate-gradle-files job and not present in the repository. On first run or with a clean cache, the hashFiles() function will return an empty hash for non-existent files, which could lead to suboptimal cache behavior.
♻️ Suggested fix: Use Cargo.lock for Gradle cache key
Since the Gradle files are generated from Cargo dependencies, using the Cargo.lock hash is more reliable:
- 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-android-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-gradle-🤖 Prompt for AI Agents
In @.github/workflows/android-build.yml around lines 317 - 325, The Cache Gradle
step's key uses hashFiles(...) against generated Gradle files (the key
expression after "key:"), which are created at runtime and may be missing;
replace that hashFiles(...) call with a hash of a stable source like Cargo.lock
(e.g., use hashFiles('Cargo.lock')) so the Gradle cache key is stable and driven
by actual dependency changes.
Split Android build into parallel jobs: 1. build-frontend: Build frontend once (shared) 2. build-rust (4x parallel): Compile each target separately - aarch64-linux-android - armv7-linux-androideabi - i686-linux-android - x86_64-linux-android 3. package-android: Download all .so files, run Gradle Each Rust job has its own sccache keyed by target for better cache hits. Expected improvement: ~10min -> ~5min (parallel Rust + Gradle) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The linker must be explicitly set when using cargo build directly (vs cargo tauri android build which sets it internally). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Generate tauri.settings.gradle in aarch64 job (contains Tauri plugin paths) - Upload as artifact and download in package-android job - Remove unnecessary bun install/setup from package-android (Gradle doesn't need node_modules) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Add generate-gradle-files job that runs in parallel with build-rust
- Keeps build-rust jobs clean (just Rust compilation)
- package-android now depends on both build-rust and generate-gradle-files
Job structure:
build-frontend ─┬─> build-rust (4x parallel) ─┬─> package-android
└─> generate-gradle-files ────┘
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Tauri generates two gradle files that are needed for packaging: - tauri.settings.gradle (in gen/android/) - tauri.build.gradle.kts (in gen/android/app/) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/android-build.yml (1)
382-394: Invalid comment syntax in.propertiesfile.The generated
tauri.propertiesuses//for comments, but.propertiesfiles use#or!for comments. The//will be treated as an invalid property line and may cause Gradle to emit warnings or fail to parse correctly.🐛 Fix comment syntax
- name: Generate tauri.properties run: | VERSION=$(jq -r '.version' frontend/src-tauri/tauri.conf.json) VERSION_CODE=$(jq -r '.bundle.android.versionCode' frontend/src-tauri/tauri.conf.json) mkdir -p frontend/src-tauri/gen/android/app cat > frontend/src-tauri/gen/android/app/tauri.properties << EOF - // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. tauri.android.versionName=$VERSION tauri.android.versionCode=$VERSION_CODE EOF
🧹 Nitpick comments (2)
.github/workflows/android-build.yml (2)
187-193: Consider verifying sccache binary integrity.The sccache installation downloads a binary from GitHub releases without checksum verification. While this is a common pattern, for supply chain security, consider verifying the download using checksums provided in the release.
♻️ Optional: Add checksum verification
- name: Install sccache run: | SCCACHE_VERSION=0.8.2 SCCACHE_URL="https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz" + SCCACHE_SHA256="<expected-sha256-here>" curl -L "$SCCACHE_URL" | tar xz + # Alternatively, download first and verify + # curl -L "$SCCACHE_URL" -o sccache.tar.gz + # echo "$SCCACHE_SHA256 sccache.tar.gz" | sha256sum -c + # tar xzf sccache.tar.gz sudo mv sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl/sccache /usr/local/bin/ chmod +x /usr/local/bin/sccache
355-368: Native library placement could benefit from explicit verification.The copy commands assume the artifact downloads succeeded. While job dependencies should ensure this, adding explicit checks would make failures more debuggable:
♻️ Optional: Add pre-copy verification
- name: Place native libraries in jniLibs run: | + set -euo pipefail + + # Verify all expected artifacts exist + for lib in aarch64 armv7 i686 x86_64; do + if [ ! -d "native-libs/android-lib-$lib" ]; then + echo "ERROR: Missing native library artifact for $lib" + exit 1 + fi + done + # Create jniLibs directories mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86,x86_64} # Copy libraries to correct locations cp native-libs/android-lib-aarch64/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-build.yml
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/android-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Handle errors with `anyhow` crate or explicit Result types in Rust code
Applied to files:
.github/workflows/android-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Run `just rust-lint` after modifying Rust code to ensure proper formatting, compilation, and linting (runs fmt + clippy strict)
Applied to files:
.github/workflows/android-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: build-rust (x86_64-linux-android, x86_64, x86_64)
- GitHub Check: build-rust (aarch64-linux-android, arm64-v8a, aarch64)
- GitHub Check: build-rust (armv7-linux-androideabi, armeabi-v7a, armv7)
- GitHub Check: build-rust (i686-linux-android, x86, i686)
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-ios
- GitHub Check: build-linux
- GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
.github/workflows/android-build.yml (6)
9-13: Environment configuration looks good.The conditional logic correctly differentiates between PR (dev) and push-to-master (production) environments. The client ID is a public OAuth identifier and is appropriately hardcoded.
15-50: Frontend build job is well-structured.The job correctly:
- Uses the larger runner for faster builds
- Pins Bun version for reproducibility
- Caches dependencies using the lockfile hash
- Uses 1-day retention for intermediate artifacts (appropriate for CI)
The top-level
envvars will be inherited, so the frontend build will pick up the correctVITE_*environment variables.
86-131: Thorough validation of generated files.The explicit verification of required Tauri Android files is excellent defensive programming. This prevents downstream failures in the
package-androidjob by catching missing files early.One minor observation: the Kotlin source check on line 118 uses
find ... | grep -q .which works but could be simplified:if ! find "$GENERATED_DIR" -type f -name "*.kt" | head -1 | grep -q .; thenHowever, the current approach is functionally correct.
219-267: Comprehensive cross-compilation environment setup.The per-target configuration correctly sets up:
- Cargo linker paths for each Android target
- C/C++ compiler and archiver paths
- Symlinks for ranlib (handles different naming conventions in build systems)
The use of Android API level 24 (Android 7.0 Nougat) provides good device coverage while supporting modern NDK features.
269-283: Rust library build and artifact upload looks correct.The build command correctly:
- Uses
--libto build only the library crate- Targets the specific Android architecture from the matrix
- Builds in release mode
The wildcard
*.sopattern should capture the native library. The sccache stats step is helpful for monitoring cache hit rates.
396-403: Gradle build configuration is correct.The
-PskipRustBuild=trueflag is essential since the Rust libraries were compiled separately in the matrix job. Building both APK and AAB with--parallelin a single invocation is efficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Upgrades all GitHub Actions workflows to use larger runners for faster builds: macos-latest-xlarge (M2, 5 cores, 14GB) and ubuntu-latest-8-cores (8 CPU, 32GB).
Major Changes
- Android build pipeline refactored into 4 parallel jobs: frontend build, Gradle file generation, Rust compilation per-ABI (4 parallel), and packaging
- RustPlugin.kt now supports
-PskipRustBuildflag for Gradle packaging stage - Environment variables moved to top-level in
android-build.ymlfor consistency - All other workflows have simple runner upgrades with no functional changes
Critical Issues Found
- Artifact path bug in
android-build.ymlwill cause nested directory structure, breaking the build (see inline comment) - The PR description notes that
ubuntu-latest-8-coresrunner must be created in org settings before merging, or all Linux/Android builds will fail immediately
Confidence Score: 2/5
- This PR has a critical artifact path bug that will break Android CI builds
- The android-build.yml refactor contains a logical error in artifact upload/download paths that will cause files to be placed in nested directories, breaking the Gradle build. Most other changes are straightforward runner upgrades with low risk. The missing SCCACHE_DIR in release.yml was already noted in previous review.
.github/workflows/android-build.ymlrequires immediate fix for artifact path handling before merging
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 2/5 | Major refactor splits Android build into 4 parallel jobs (frontend, gradle files, rust builds per-target, packaging). Critical bug: artifact paths will create nested directories causing build failure. |
| .github/workflows/desktop-build.yml | 5/5 | Simple runner upgrade from macos-latest to macos-latest-xlarge and ubuntu-latest to ubuntu-latest-8-cores. No functional changes. |
| .github/workflows/mobile-build.yml | 5/5 | Simple runner upgrade from macos-latest to macos-latest-xlarge for iOS builds. No functional changes. |
| .github/workflows/release.yml | 5/5 | Runner upgrades across all jobs. Already noted issue with missing SCCACHE_DIR for Linux builds in previous review thread. |
| .github/workflows/testflight-on-comment.yml | 5/5 | Runner upgrades for both check-comment job (ubuntu-latest-8-cores) and deploy-testflight job (macos-latest-xlarge). No functional changes. |
| .github/workflows/claude.yml | 5/5 | Simple runner upgrade from ubuntu-latest to ubuntu-latest-8-cores. No functional changes. |
| frontend/src-tauri/gen/android/buildSrc/src/main/java/cloud/opensecret/maple/kotlin/RustPlugin.kt | 5/5 | Adds skipRustBuild property support to allow Gradle to skip Rust compilation when pre-built libraries are provided. Required for new parallel build strategy. |
Sequence Diagram
sequenceDiagram
participant Trigger as Workflow Trigger
participant Frontend as build-frontend
participant Gradle as generate-gradle-files
participant Rust1 as build-rust (aarch64)
participant Rust2 as build-rust (armv7)
participant Rust3 as build-rust (i686)
participant Rust4 as build-rust (x86_64)
participant Package as package-android
participant Artifacts as GitHub Artifacts
Trigger->>Frontend: Start CI build
Trigger->>Gradle: Start CI build
Note over Frontend: Build frontend with Bun<br/>Uses VITE env vars
Frontend->>Artifacts: Upload frontend-dist
Note over Gradle: Generate Tauri Android files<br/>cargo tauri android init --ci
Gradle->>Artifacts: Upload tauri-android-generated
Artifacts->>Rust1: Download frontend-dist
Artifacts->>Rust2: Download frontend-dist
Artifacts->>Rust3: Download frontend-dist
Artifacts->>Rust4: Download frontend-dist
Note over Rust1,Rust4: Parallel Rust compilation<br/>for each Android ABI<br/>with sccache
Rust1->>Artifacts: Upload android-lib-aarch64
Rust2->>Artifacts: Upload android-lib-armv7
Rust3->>Artifacts: Upload android-lib-i686
Rust4->>Artifacts: Upload android-lib-x86_64
Artifacts->>Package: Download frontend-dist
Artifacts->>Package: Download tauri-android-generated
Artifacts->>Package: Download all android-lib-*
Note over Package: Place files in jniLibs<br/>Run Gradle with -PskipRustBuild=true<br/>Build APK and AAB
Package->>Artifacts: Upload APK & AAB
| path: | | ||
| frontend/src-tauri/gen/android/tauri.settings.gradle | ||
| frontend/src-tauri/gen/android/.tauri/** | ||
| frontend/src-tauri/gen/android/app/tauri.build.gradle.kts | ||
| frontend/src-tauri/gen/android/app/src/main/assets/tauri.conf.json | ||
| frontend/src-tauri/gen/android/app/src/main/java/**/generated/** | ||
| frontend/src-tauri/gen/android/app/proguard-tauri.pro | ||
| retention-days: 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Artifact upload paths will cause incorrect directory structure when downloaded.
When uploading with paths like frontend/src-tauri/gen/android/tauri.settings.gradle, the artifact preserves this full path. When downloaded to tauri-android-generated, it extracts as tauri-android-generated/frontend/src-tauri/gen/android/....
Then at line 348, cp -R tauri-android-generated/. frontend/src-tauri/gen/android/ copies all contents, resulting in nested paths: frontend/src-tauri/gen/android/frontend/src-tauri/gen/android/...
Fix by adding working-directory:
| path: | | |
| frontend/src-tauri/gen/android/tauri.settings.gradle | |
| frontend/src-tauri/gen/android/.tauri/** | |
| frontend/src-tauri/gen/android/app/tauri.build.gradle.kts | |
| frontend/src-tauri/gen/android/app/src/main/assets/tauri.conf.json | |
| frontend/src-tauri/gen/android/app/src/main/java/**/generated/** | |
| frontend/src-tauri/gen/android/app/proguard-tauri.pro | |
| retention-days: 1 | |
| - name: Upload Tauri Android generated files | |
| working-directory: ./frontend | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: tauri-android-generated | |
| path: | | |
| src-tauri/gen/android/tauri.settings.gradle | |
| src-tauri/gen/android/.tauri/** | |
| src-tauri/gen/android/app/tauri.build.gradle.kts | |
| src-tauri/gen/android/app/src/main/assets/tauri.conf.json | |
| src-tauri/gen/android/app/src/main/java/**/generated/** | |
| src-tauri/gen/android/app/proguard-tauri.pro |
Then update line 348 to: cp -R tauri-android-generated/src-tauri/gen/android/. frontend/src-tauri/gen/android/
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 137:144
Comment:
Artifact upload paths will cause incorrect directory structure when downloaded.
When uploading with paths like `frontend/src-tauri/gen/android/tauri.settings.gradle`, the artifact preserves this full path. When downloaded to `tauri-android-generated`, it extracts as `tauri-android-generated/frontend/src-tauri/gen/android/...`.
Then at line 348, `cp -R tauri-android-generated/. frontend/src-tauri/gen/android/` copies all contents, resulting in nested paths: `frontend/src-tauri/gen/android/frontend/src-tauri/gen/android/...`
Fix by adding `working-directory`:
```suggestion
- name: Upload Tauri Android generated files
working-directory: ./frontend
uses: actions/upload-artifact@v4
with:
name: tauri-android-generated
path: |
src-tauri/gen/android/tauri.settings.gradle
src-tauri/gen/android/.tauri/**
src-tauri/gen/android/app/tauri.build.gradle.kts
src-tauri/gen/android/app/src/main/assets/tauri.conf.json
src-tauri/gen/android/app/src/main/java/**/generated/**
src-tauri/gen/android/app/proguard-tauri.pro
```
Then update line 348 to: `cp -R tauri-android-generated/src-tauri/gen/android/. frontend/src-tauri/gen/android/`
How can I resolve this? If you propose a fix, please make it concise.Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
e1b2c4c to
79e2d43
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Refactors Android build pipeline into four modular jobs that run in parallel for faster builds. Frontend is built once and shared, Rust compilation happens in parallel for all 4 Android targets (aarch64, armv7, i686, x86_64), and Gradle packages everything together.
Major changes:
- Frontend build separated into its own job with artifact sharing
- New
generate-gradle-filesjob creates Tauri Android metadata without compiling Rust - Rust builds parallelized using matrix strategy with per-target caching
RustPlugin.ktupdated with-PskipRustBuildflag to skip Rust compilation during Gradle packaging- Cross-compilation environment setup moved to individual build-rust jobs
Issues found:
- Missing environment variables during frontend build (lines 40-42) - Vite won't embed
VITE_*vars cargo fetchmissing--lockedflag (line 92) - may cause dependency inconsistenciesskipRustBuildproperty logic flaw (RustPlugin.kt:20-23) - would activate even with-PskipRustBuild=false- No verification that
.sofiles exist before upload/copy operations - Artifact download patterns may create unexpected directory nesting
Confidence Score: 3/5
- This PR has significant build improvements but contains critical bugs that will cause build failures
- The refactoring is well-structured with good parallelization strategy, but has two critical issues: (1) missing environment variables during frontend build will produce incorrect builds, and (2) the skipRustBuild property check logic is flawed. Additional concerns include missing error handling for artifact operations and potential directory structure mismatches.
- Pay close attention to
.github/workflows/android-build.ymllines 40-42 (missing env vars) and 92 (cargo fetch), andRustPlugin.ktlines 20-23 (property check logic)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/android-build.yml | 3/5 | Refactored Android build into modular jobs with parallel Rust builds. Found issues with env vars, artifact handling, and error checking. |
| frontend/src-tauri/gen/android/buildSrc/src/main/java/cloud/opensecret/maple/kotlin/RustPlugin.kt | 3/5 | Added skipRustBuild flag to allow Gradle packaging without rebuilding Rust. Logic has potential issue with property checking. |
Sequence Diagram
sequenceDiagram
participant GH as GitHub Actions
participant Frontend as build-frontend
participant Gradle as generate-gradle-files
participant Rust1 as build-rust (aarch64)
participant Rust2 as build-rust (armv7)
participant Rust3 as build-rust (i686)
participant Rust4 as build-rust (x86_64)
participant Package as package-android
GH->>Frontend: Start frontend build
GH->>Gradle: Start Gradle file generation
Frontend->>Frontend: bun install & build
Frontend->>GH: Upload frontend/dist artifact
Gradle->>Gradle: cargo tauri android init --ci
Gradle->>Gradle: Copy generated files to stable path
Gradle->>GH: Upload tauri-android-generated artifact
Frontend->>GH: Frontend complete
GH->>Rust1: Start Rust build (parallel)
GH->>Rust2: Start Rust build (parallel)
GH->>Rust3: Start Rust build (parallel)
GH->>Rust4: Start Rust build (parallel)
Rust1->>Rust1: Download frontend/dist
Rust1->>Rust1: cargo build --target aarch64
Rust1->>GH: Upload android-lib-aarch64 artifact
Rust2->>Rust2: Download frontend/dist
Rust2->>Rust2: cargo build --target armv7
Rust2->>GH: Upload android-lib-armv7 artifact
Rust3->>Rust3: Download frontend/dist
Rust3->>Rust3: cargo build --target i686
Rust3->>GH: Upload android-lib-i686 artifact
Rust4->>Rust4: Download frontend/dist
Rust4->>Rust4: cargo build --target x86_64
Rust4->>GH: Upload android-lib-x86_64 artifact
Gradle->>GH: Gradle complete
Rust1->>GH: All Rust builds complete
GH->>Package: Start packaging
Package->>Package: Download frontend/dist
Package->>Package: Download all android-lib-* artifacts
Package->>Package: Download tauri-android-generated
Package->>Package: Place generated files & .so libs
Package->>Package: gradlew assembleUniversalRelease -PskipRustBuild=true
Package->>GH: Upload APK and AAB artifacts
| - name: Build frontend | ||
| working-directory: ./frontend | ||
| run: bun run build |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Frontend build doesn't use the workflow-level env vars. The VITE_* environment variables defined at lines 10-12 need to be available during the build step for Vite to embed them.
| - name: Build frontend | |
| working-directory: ./frontend | |
| run: bun run build | |
| - name: Build frontend | |
| working-directory: ./frontend | |
| run: bun run build | |
| env: | |
| VITE_OPEN_SECRET_API_URL: ${{ env.VITE_OPEN_SECRET_API_URL }} | |
| VITE_MAPLE_BILLING_API_URL: ${{ env.VITE_MAPLE_BILLING_API_URL }} | |
| VITE_CLIENT_ID: ${{ env.VITE_CLIENT_ID }} |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 40:42
Comment:
Frontend build doesn't use the workflow-level env vars. The `VITE_*` environment variables defined at lines 10-12 need to be available during the build step for Vite to embed them.
```suggestion
- name: Build frontend
working-directory: ./frontend
run: bun run build
env:
VITE_OPEN_SECRET_API_URL: ${{ env.VITE_OPEN_SECRET_API_URL }}
VITE_MAPLE_BILLING_API_URL: ${{ env.VITE_MAPLE_BILLING_API_URL }}
VITE_CLIENT_ID: ${{ env.VITE_CLIENT_ID }}
```
How can I resolve this? If you propose a fix, please make it concise.| - name: Download all native libraries | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| pattern: android-lib-* | ||
| path: native-libs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Artifact download with pattern: android-lib-* creates nested directory structure. Each artifact will be in its own subdirectory under native-libs/, potentially like native-libs/android-lib-aarch64/android-lib-aarch64/*.so. Verify the actual structure matches expectations at line 401-404.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 373:377
Comment:
Artifact download with `pattern: android-lib-*` creates nested directory structure. Each artifact will be in its own subdirectory under `native-libs/`, potentially like `native-libs/android-lib-aarch64/android-lib-aarch64/*.so`. Verify the actual structure matches expectations at line 401-404.
How can I resolve this? If you propose a fix, please make it concise.| - name: Upload native library | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: android-lib-${{ matrix.short_name }} | ||
| path: frontend/src-tauri/target/${{ matrix.target }}/release/*.so | ||
| retention-days: 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No verification that .so files exist before upload. If cargo build succeeds but doesn't produce expected libraries, upload will fail silently or upload nothing.
Add verification:
- name: Verify library was built
run: |
if [ ! -f frontend/src-tauri/target/${{ matrix.target }}/release/*.so ]; then
echo "ERROR: No .so files found"
exit 1
fi
ls -la frontend/src-tauri/target/${{ matrix.target }}/release/*.so
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 317:322
Comment:
No verification that `.so` files exist before upload. If cargo build succeeds but doesn't produce expected libraries, upload will fail silently or upload nothing.
Add verification:
```
- name: Verify library was built
run: |
if [ ! -f frontend/src-tauri/target/${{ matrix.target }}/release/*.so ]; then
echo "ERROR: No .so files found"
exit 1
fi
ls -la frontend/src-tauri/target/${{ matrix.target }}/release/*.so
```
How can I resolve this? If you propose a fix, please make it concise.| - name: Place native libraries in jniLibs | ||
| run: | | ||
| # Create jniLibs directories | ||
| mkdir -p frontend/src-tauri/gen/android/app/src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86,x86_64} | ||
| # Copy libraries to correct locations | ||
| cp native-libs/android-lib-aarch64/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/ | ||
| cp native-libs/android-lib-armv7/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/armeabi-v7a/ | ||
| cp native-libs/android-lib-i686/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86/ | ||
| cp native-libs/android-lib-x86_64/*.so frontend/src-tauri/gen/android/app/src/main/jniLibs/x86_64/ | ||
| # Verify | ||
| echo "=== Native libraries placed ===" | ||
| find frontend/src-tauri/gen/android/app/src/main/jniLibs -name "*.so" -exec ls -la {} \; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No error handling if .so files are missing from any architecture. The cp commands will fail but won't stop execution without set -e.
Add verification before Gradle build:
- name: Verify all native libraries
run: |
MISSING=0
for arch in arm64-v8a armeabi-v7a x86 x86_64; do
if [ ! -f frontend/src-tauri/gen/android/app/src/main/jniLibs/$arch/*.so ]; then
echo "ERROR: Missing .so for $arch"
MISSING=1
fi
done
if [ $MISSING -eq 1 ]; then exit 1; fi
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 395:408
Comment:
No error handling if `.so` files are missing from any architecture. The `cp` commands will fail but won't stop execution without `set -e`.
Add verification before Gradle build:
```
- name: Verify all native libraries
run: |
MISSING=0
for arch in arm64-v8a armeabi-v7a x86 x86_64; do
if [ ! -f frontend/src-tauri/gen/android/app/src/main/jniLibs/$arch/*.so ]; then
echo "ERROR: Missing .so for $arch"
MISSING=1
fi
done
if [ $MISSING -eq 1 ]; then exit 1; fi
```
How can I resolve this? If you propose a fix, please make it concise.| - name: Generate Tauri Android files | ||
| working-directory: ./frontend | ||
| run: | | ||
| set -euo pipefail | ||
| # Ensure all Tauri + plugin crates exist in the cargo registry so tauri.settings.gradle can be generated. | ||
| cargo fetch --locked --manifest-path src-tauri/Cargo.toml | ||
| # Generate Android project + required autogen files without compiling Rust. | ||
| cargo tauri android init --ci |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing --locked flag on cargo fetch. Without it, Cargo may update dependencies beyond what's in Cargo.lock, causing inconsistencies between this job and the build-rust jobs.
| - name: Generate Tauri Android files | |
| working-directory: ./frontend | |
| run: | | |
| set -euo pipefail | |
| # Ensure all Tauri + plugin crates exist in the cargo registry so tauri.settings.gradle can be generated. | |
| cargo fetch --locked --manifest-path src-tauri/Cargo.toml | |
| # Generate Android project + required autogen files without compiling Rust. | |
| cargo tauri android init --ci | |
| # Ensure all Tauri + plugin crates exist in the cargo registry so tauri.settings.gradle can be generated. | |
| cargo fetch --locked --manifest-path src-tauri/Cargo.toml | |
| # Generate Android project + required autogen files without compiling Rust. | |
| cargo tauri android init --ci |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 86:95
Comment:
Missing `--locked` flag on `cargo fetch`. Without it, Cargo may update dependencies beyond what's in `Cargo.lock`, causing inconsistencies between this job and the `build-rust` jobs.
```suggestion
# Ensure all Tauri + plugin crates exist in the cargo registry so tauri.settings.gradle can be generated.
cargo fetch --locked --manifest-path src-tauri/Cargo.toml
# Generate Android project + required autogen files without compiling Rust.
cargo tauri android init --ci
```
How can I resolve this? If you propose a fix, please make it concise.| val skipRustBuild = | ||
| (findProperty("skipRustBuild") as? String)?.toBooleanStrictOrNull() == true || | ||
| (findProperty("skipRustBuild") as? Boolean) == true || | ||
| hasProperty("skipRustBuild") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hasProperty("skipRustBuild") on line 23 returns true even if property is explicitly set to "false". Using -PskipRustBuild=false would still skip the build.
| val skipRustBuild = | |
| (findProperty("skipRustBuild") as? String)?.toBooleanStrictOrNull() == true || | |
| (findProperty("skipRustBuild") as? Boolean) == true || | |
| hasProperty("skipRustBuild") | |
| val skipRustBuild = | |
| (findProperty("skipRustBuild") as? String)?.toBooleanStrictOrNull() == true || | |
| (findProperty("skipRustBuild") as? Boolean) == true |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/gen/android/buildSrc/src/main/java/cloud/opensecret/maple/kotlin/RustPlugin.kt
Line: 20:23
Comment:
`hasProperty("skipRustBuild")` on line 23 returns true even if property is explicitly set to "false". Using `-PskipRustBuild=false` would still skip the build.
```suggestion
val skipRustBuild =
(findProperty("skipRustBuild") as? String)?.toBooleanStrictOrNull() == true ||
(findProperty("skipRustBuild") as? Boolean) == true
```
How can I resolve this? If you propose a fix, please make it concise.| - name: Place Tauri Android generated files | ||
| run: | | ||
| # Copy generated files into the checked out Android project | ||
| cp -R tauri-android-generated/. frontend/src-tauri/gen/android/ | ||
| echo "=== Tauri generated files placed ===" | ||
| ls -la frontend/src-tauri/gen/android/tauri.settings.gradle | ||
| ls -la frontend/src-tauri/gen/android/app/tauri.build.gradle.kts | ||
| ls -la frontend/src-tauri/gen/android/app/src/main/assets/tauri.conf.json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using cp -R with trailing /. copies directory contents, but if the source path structure doesn't match expectations (e.g., if tauri-android-generated has an extra nesting level), files may not end up in the right place. Add verification after copy to ensure critical files exist.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/android-build.yml
Line: 385:393
Comment:
Using `cp -R` with trailing `/.` copies directory contents, but if the source path structure doesn't match expectations (e.g., if `tauri-android-generated` has an extra nesting level), files may not end up in the right place. Add verification after copy to ensure critical files exist.
How can I resolve this? If you propose a fix, please make it concise.
Summary
Upgrades all GitHub Actions workflows to use larger runners for faster builds.
Changes
macos-latest(3-core M1, 7GB)macos-latest-xlargeubuntu-latest(2 CPU, 7GB)ubuntu-latest-8-coresWorkflows Updated
desktop-build.yml- macOS and Linux buildsmobile-build.yml- iOS buildsrelease.yml- Release builds (macOS, Linux, Android)android-build.yml- Android CI buildstestflight-on-comment.yml- TestFlight deploymentsclaude.yml- Claude Code automationSetup Required
Before merging, create the Ubuntu larger runner in your org settings:
ubuntu-latest-8-coresThe macOS
macos-latest-xlargerunner works automatically with no setup needed.Expected Impact
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.