Skip to content

feat(plugin-tauri): self-healing Android builds with APK artifacts - #69

Open
Armaldio wants to merge 5 commits into
developfrom
t9/tauri-mobile-android
Open

feat(plugin-tauri): self-healing Android builds with APK artifacts#69
Armaldio wants to merge 5 commits into
developfrom
t9/tauri-mobile-android

Conversation

@Armaldio

Copy link
Copy Markdown
Member

Summary

Adds Android (and iOS) mobile packaging support to the Tauri plugin and makes the pipeline self-heal its toolchain so it builds on a host that only has node/pnpm + Rust pre-installed (no mise).

  • Build Android/iOS via tauri <platform> init then tauri <platform> build --target <triple> [--apk].
  • Self-heal the Android SDK/NDK: reuse an existing SDK (env ANDROID_HOME, ~/Android/Sdk, mise, /opt) or download the command-line tools and provision platform-tools, platforms;android-34, build-tools;34.0.0, ndk;26.1.10909125 into the shared cache folder; add the aarch64-linux-android Rust target.
  • Pin @tauri-apps/* npm versions to the resolved Rust crate versions (via cargo metadata) so Tauri's version-mismatch check passes.
  • Discover the produced APK recursively (Tauri names it per target, e.g. app-universal-release-unsigned.apk) and register it as a pipeline artifact so it persists beyond the build sandbox; outputs (output/binary) still point at the sandbox build dir.
  • Prefer the local asset template (fetchPipelabAsset) so pinned Cargo dependencies are used offline.
  • Add an example Tauri mobile pipeline (examples/tauri-mobile-pipeline).

Cache / convention notes

  • Android SDK and CARGO_TARGET_DIR live under paths.cache = getCachePath(CacheFolder.Pipelines, <pipelineId>) (the shared pipeline cache folder).
  • The APK is persisted via setArtifact, copied by the runner to getArtifactsPath(pipelineId, buildId).
  • Build runs inside the createTempFolder() sandbox; only the APK is copied out.

Conflict to flag

The Android SDK/NDK is several GB and is currently stored per-pipeline (under CacheFolder.Pipelines/<pipelineId>), so multiple Android pipelines duplicate it. It is also stored in userData/cache, which on disk-constrained hosts can exhaust space (the reason we symlinked @pipelab/app-dev/tmp in this environment). Follow-ups: store the SDK at a pipeline-independent cache location (or a dedicated toolchain cache folder) and/or document pointing settings.cacheFolder at a larger volume.

Test plan

  • pnpm --filter @pipelab/cli start -- run examples/tauri-mobile-pipeline/pipeline.json produces EXIT=0 and an APK copied to artifacts/<pipelineId>/<buildId>/app-universal-release-unsigned.apk (verified).

🤖 Generated with opencode

- Build Android (and iOS) apps via `tauri <platform> init` + `tauri <platform> build`
- Self-heal the Android toolchain: reuse an existing SDK or download the
  command-line tools and provision NDK/build-tools/platform into the shared
  cache folder; add the aarch64-linux-android Rust target
- Pin @tauri-apps/* npm versions to the resolved Rust crate versions so Tauri's
  version-mismatch check passes
- Discover the produced APK recursively (Tauri names it per target) and register
  it as a pipeline artifact so it persists beyond the build sandbox
- Prefer the local asset template so pinned Cargo dependencies are used offline
- Add an example Tauri mobile pipeline
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploying pipelab with  Cloudflare Pages  Cloudflare Pages

Latest commit: ac6130c
Status: ✅  Deploy successful!
Preview URL: https://8944d5ee.pipelab.pages.dev
Branch Preview URL: https://t9-tauri-mobile-android.pipelab.pages.dev

View logs

… cache

Previously the SDK/NDK (several GB) was written under the per-pipeline cache
(CacheFolder.Pipelines/<pipelineId>), so every Android pipeline re-downloaded
its own copy. Point ensureAndroidEnvironment at
getCachePath('Pipelines')/android-sdk so the toolchain is shared across all
pipelines.
@pkg-pr-new

pkg-pr-new Bot commented Aug 14, 2026

Copy link
Copy Markdown

Open in StackBlitz

@pipelab/asset-discord

npm i https://pkg.pr.new/@pipelab/asset-discord@69

@pipelab/asset-electron

npm i https://pkg.pr.new/@pipelab/asset-electron@69

@pipelab/asset-netlify

npm i https://pkg.pr.new/@pipelab/asset-netlify@69

@pipelab/asset-tauri

npm i https://pkg.pr.new/@pipelab/asset-tauri@69

@pipelab/plugin-construct

npm i https://pkg.pr.new/@pipelab/plugin-construct@69

@pipelab/plugin-core

npm i https://pkg.pr.new/@pipelab/plugin-core@69

@pipelab/plugin-discord

npm i https://pkg.pr.new/@pipelab/plugin-discord@69

@pipelab/plugin-electron

npm i https://pkg.pr.new/@pipelab/plugin-electron@69

@pipelab/plugin-filesystem

npm i https://pkg.pr.new/@pipelab/plugin-filesystem@69

@pipelab/plugin-itch

npm i https://pkg.pr.new/@pipelab/plugin-itch@69

@pipelab/plugin-minify

npm i https://pkg.pr.new/@pipelab/plugin-minify@69

@pipelab/plugin-netlify

npm i https://pkg.pr.new/@pipelab/plugin-netlify@69

@pipelab/plugin-nvpatch

npm i https://pkg.pr.new/@pipelab/plugin-nvpatch@69

@pipelab/plugin-poki

npm i https://pkg.pr.new/@pipelab/plugin-poki@69

@pipelab/plugin-steam

npm i https://pkg.pr.new/@pipelab/plugin-steam@69

@pipelab/plugin-system

npm i https://pkg.pr.new/@pipelab/plugin-system@69

@pipelab/plugin-tauri

npm i https://pkg.pr.new/@pipelab/plugin-tauri@69

@pipelab/constants

npm i https://pkg.pr.new/@pipelab/constants@69

@pipelab/core-node

npm i https://pkg.pr.new/@pipelab/core-node@69

@pipelab/migration

npm i https://pkg.pr.new/@pipelab/migration@69

@pipelab/shared

npm i https://pkg.pr.new/@pipelab/shared@69

commit: ac6130c

Use context.getCachePath() (the cache base, alongside pacote) instead of the
per-pipeline cache so the SDK lives at cache/android-sdk. Also fixes a
typecheck bug: the CacheFolder value is lowercase 'pipelines', so the previous
getCachePath('Pipelines') literal would fail the typecheck.
…on field

- Remove the mobileConfig input: it was merged into completeConfiguration.mobile
  but then deleted before the config was written (to stay valid across Tauri
  2.x), so it silently did nothing and was misleading.
- Remove the unused `configuration` field from the shared params const (the
  package action uses configureParams, not it).
- Update the example pipeline accordingly.
…ld path

- Add TargetPlatform/TargetArch types (NodeJS.Platform/Architecture don't know
  about android/ios/armv7l/universal/mips64el) and use them for the platform/
  arch param values, the handler's finalPlatform/finalArch, and the mobile
  target-resolution helpers.
- Export ensureAndroidEnvironment/findAndroidApk/resolveMobileCliTarget/
  resolveMobileOutputTriple (and re-export from the plugin entry) so future
  mobile-first plugins can reuse the SDK provisioning and target resolution.
- Example now builds the SAME app for both desktop (linux) and android from one
  input folder.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant