Skip to content

ci(mobile): pass required toolchain input to dtolnay/rust-toolchain@v1 - #495

Merged
Ziinc merged 18 commits into
mainfrom
claude/mobile-ci-workflows-audit-bthpmm
Sep 23, 2026
Merged

Ziinc merged 18 commits into
mainfrom
claude/mobile-ci-workflows-audit-bthpmm

Conversation

@Ziinc

@Ziinc Ziinc commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Both android and ios jobs failed immediately at the 'Install Rust stable'
step: dtolnay/rust-toolchain@v1 requires a toolchain input and every
other workflow in the repo passes toolchain: stable, but mobile.yml only
passed targets, so the action errored out before any build work ran.

Both android and ios jobs failed immediately at the 'Install Rust stable'
step: dtolnay/rust-toolchain@v1 requires a toolchain input and every
other workflow in the repo passes toolchain: stable, but mobile.yml only
passed targets, so the action errored out before any build work ran.
Android: android-actions/setup-android@v3 defaults to installing the
legacy 'tools' package alongside 'platform-tools'; Google removed
'tools' from the SDK repository, so sdkmanager errored with
"Failed to find package 'tools'". Override packages to platform-tools
only.

iOS: 'tauri ios build --debug' still runs xcodebuild with automatic
signing and fails with "Signing for treq_iOS requires a development
team" since CI has no Apple developer team configured. The job is
named/labelled an unsigned debug build, so pass --no-sign to actually
skip code signing.
--no-sign errored with 'unexpected argument' because the repo pins
@tauri-apps/cli 2.10.1, which predates that flag. This CLI does support
forwarding raw args to xcodebuild via 'tauri ios build -- ARGS', so
disable signing at the xcodebuild level instead:
CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=
--no-sign was added after 2.10.1; the repo's existing ^2.10.0 range
already permits it, the lockfile was just stale. Bumped to 2.11.4 (npm
install within the existing semver range) and reverted the previous
ARGS-forwarding workaround, which turned out to pass through to the
Rust/cargo build rather than xcodebuild and had no effect. --no-sign is
the CLI's actual, documented way to skip code signing.
… drift

The Android build is the first time this Rust code has ever been
compiled for a mobile target (67 prior CI runs all failed before
reaching cargo build). It surfaced real, pre-existing incompatibilities:

- lib.rs: the native menu (tauri::menu, set_menu, on_menu_event) and the
  two folder-picker helpers (FileDialogBuilder::pick_folder) have no
  mobile implementation in Tauri. Gated behind #[cfg(desktop)], matching
  the existing #[cfg(mobile)]/#[cfg(desktop)] convention already used
  for the keystore/biometric plugins and the deep-link handler.

- commands/browser_webview.rs: the embedded browser-preview panel uses
  Webview::set_position/set_size/close and Window::add_child, none of
  which exist on mobile. Split into #[cfg(desktop)] real implementations
  and #[cfg(not(desktop))] stubs that return an error, so the Tauri
  command list in lib.rs doesn't need a platform-specific branch.

- core/remote_device_key.rs + commands/remote.rs: tauri-plugin-keystore
  2.1.0-alpha.2 (resolved by the unpinned "2.1.0-alpha.1" Cargo.toml
  requirement) changed store()/retrieve() to async and replaced
  RetrieveRequest's service/user fields and StoreRequest's bare value
  field with a single key + optional prompt. Updated both call sites and
  threaded the new async-ness through ensure_mobile_device_key. Also
  fixed a type mismatch: PrivateKey::to_openssh returns Zeroizing<String>,
  not String.
The signed android-release/ios-release jobs main added carry the same
dtolnay/rust-toolchain missing-input and legacy-'tools'-package bugs
already fixed on the unsigned debug jobs. Port the same two fixes.
@Ziinc
Ziinc force-pushed the claude/mobile-ci-workflows-audit-bthpmm branch from aa2177e to a12f08d Compare September 19, 2026 05:30
…sign

--no-sign (available since @tauri-apps/cli 2.11) turned out to skip the
plain 'xcodebuild build' entirely and always archive+export instead
(confirmed against the CLI's build.rs: build only runs when neither
archive_only nor no_sign is set), which needs its own signing/export
plumbing and produces an .ipa rather than the .app this job's Upload
step expects. That surfaced as an unrelated-looking 'npm error Missing
script: tauri' inside the archive's Run Script build phase.

Went back to the plain 'build' action and disabled signing the way
xcodebuild actually supports for it: CODE_SIGNING_ALLOWED/REQUIRED and
CODE_SIGN_IDENTITY as step-level env vars, which xcodebuild picks up as
build-setting overrides since the generated project doesn't hardcode
them - the standard pattern for CI-unsigned iOS builds.
Plain CODE_SIGNING_ALLOWED/REQUIRED env vars didn't clear 'requires a
development team' - that check fires specifically because the generated
Xcode project has automatic signing enabled, which needs a resolvable
team account regardless of those two settings. Add CODE_SIGN_STYLE=Manual
and an empty DEVELOPMENT_TEAM to actually turn automatic signing off.
…v vars

Neither --no-sign (forces archive+export, wrong artifact shape, and hits
a separate npm-script bug) nor xcodebuild env-var overrides
(CODE_SIGN_STYLE/CODE_SIGNING_ALLOWED/etc - confirmed to have zero
effect on this build path) get the plain 'xcodebuild build' action past
'Signing for treq_iOS requires a development team'. Leaving the env vars
in place was dead weight; documenting the blocker and the two ruled-out
approaches instead so this doesn't get rediscovered from scratch.

Ziinc commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator Author

Status: android build (unsigned debug) green, ios build (unsigned debug) blocked

Android and the Rust compile errors that surfaced once CI-config bugs were cleared (desktop-only Tauri APIs, tauri-plugin-keystore API drift) are fixed as of f236a76.

iOS unsigned debug build is currently blocked on xcodebuild's Signing for "treq_iOS" requires a development team error. Two approaches were tried and ruled out (details/commit refs in the workflow file's comment above the Build unsigned debug app bundle step):

  1. tauri ios build --debug --no-sign — the CLI's own flag for this (added in @tauri-apps/cli 2.11+). It does skip signing, but it also skips the plain xcodebuild build this job wants and always archives+exports instead (confirmed against the CLI source: build only runs when neither archive_only nor no_sign is set). That needs its own export/signing plumbing, produces a .ipa rather than the .app this job uploads, and separately failed on an unrelated npm error Missing script: "tauri" inside the archive's own "Build Rust Code" run-script phase.
  2. Setting CODE_SIGNING_ALLOWED/CODE_SIGNING_REQUIRED/CODE_SIGN_IDENTITY/CODE_SIGN_STYLE/DEVELOPMENT_TEAM as step-level env vars (the standard xcodebuild-reads-env-as-override trick) — had zero measurable effect; identical error, and no "codesigning identity override" note in the log for this path (unlike the --no-sign path, where that note does appear), meaning Xcode's automatic-signing validation runs before it would consult process-environment overrides.

Root-causing further needs to inspect the actual generated gen/apple/treq.xcodeproj (particularly its "Build Rust Code" run-script phase and default CODE_SIGN_STYLE), which needs a real macOS/Xcode environment to reproduce — not available in the sandbox these fixes were made from.


Generated by Claude Code

Manifest merge failed: tauri-plugin-keystore 2.1.0-alpha.2's Android
manifest declares minSdk 28, but the app defaulted to Tauri's
template minSdk of 24. Set bundle.android.minSdkVersion explicitly.
minSdkVersion 28 fixed the manifest-merger failure, but the android job
now fails differently: Gradle's rustBuildArm64Debug task shells out to
npm and hits 'npm error Missing script: "tauri"' - the same failure
iOS's --no-sign archive path hit, now confirmed NOT archive-specific
but a shared bug in how the generated native build tooling re-invokes
the tauri CLI. BuildTask.kt (the generated Gradle task) picks its own
verbosity for that recursive call from TAURI_CLI_VERBOSITY; bump it to
see the exact command line and working directory it uses.
Root cause of the 'npm error Missing script: "tauri"' failure on both
android and ios (previously misdiagnosed as iOS-archive-specific):
Tauri's generated native build tooling (Android's Gradle rustBuild
task via BuildTask.kt, iOS's 'Build Rust Code' Xcode script phase)
re-invokes itself via 'npm run tauri', with its working directory
resolved to src-tauri (confirmed against BuildTask.kt's template
source: workingDir is project.projectDir + rootDirRel, which points at
the Cargo project root, not the npm project root).

src-tauri/package.json exists deliberately (to mark that subtree
'type: commonjs', overriding the root's 'type: module') but had no
scripts, so npm stopped there instead of walking up to the root
package.json's 'tauri' script. Added the same passthrough script;
@tauri-apps/cli resolves fine from there since npm's script PATH
includes every ancestor directory's node_modules/.bin up to root.

Also drops the TAURI_CLI_VERBOSITY=2 diagnostic env var added to track
this down, now that the root cause is fixed.

Ziinc commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator Author

Update: root-caused and fixed the npm error Missing script: "tauri" bug

Correction to my earlier comment: that failure is not iOS/archive-specific. It also hit Android's android build (unsigned debug) job (inside Gradle's rustBuildArm64Debug task) once the minSdkVersion fix (25d2bdc) got that job past its own, separate manifest-merger failure.

Root cause: Tauri's generated native build tooling re-invokes itself via npm run tauri — confirmed against the actual BuildTask.kt template source (Android's Gradle task runs project.exec { workingDir(File(project.projectDir, rootDirRel)); executable("{{tauri-binary}}") ... }, and {{tauri-binary}} gets substituted with npm run tauri at tauri android init time). That workingDir resolves to src-tauri (the Cargo project root), not the repo root where package.json's "tauri": "tauri" script actually lives — and src-tauri/package.json exists (deliberately, to mark that subtree "type": "commonjs", overriding the root's "type": "module") but had no scripts at all. npm stops at the nearest package.json it finds walking up from cwd, so it never reached the root one.

Fix (8f30fef): added the same "tauri": "tauri" passthrough script to src-tauri/package.json. @tauri-apps/cli resolves fine from there since npm's script PATH includes every ancestor directory's node_modules/.bin up to the repo root.

Current status

  • Android: all known issues fixed (toolchain, SDK package, Rust compile errors, minSdkVersion, and now this). Watching the run on 8f30fef to confirm green.
  • iOS: still blocked, but now purely on the xcodebuild "requires a development team" signing error for the plain build action — the npm-script bug that used to also hit the --no-sign/archive path is fixed, but that path still has the wrong-artifact-type problem (produces .ipa, this job wants .app) and the plain-build path still hasn't found a working signing bypass. Root-causing that further needs a real macOS/Xcode environment to reproduce, which I don't have in this sandbox.

Generated by Claude Code

Pre-existing formatting drift in files unrelated to this PR's changes
(last touched by #494), caught by verify-rust/fmt once this branch
picked up current main.
…anches

test-js/test:integration failed: 'duplicate #[tauri::command] function
name found: open_browser_webview'. This crate's tauri-test-macros
proc macro (used by TauriTestApp/tauri_test_bridge for the NAPI test
bridge) discovers #[tauri::command] functions by scanning source text,
not by evaluating #[cfg] - so the desktop/mobile-stub pair of
same-named command functions added for mobile CI (0e52953) reads as a
genuine duplicate to it, even though rustc would only ever compile one.

Matches the pattern already used in core/remote_device_key.rs's
ensure_device_key: keep each #[tauri::command] function defined once,
unconditionally, and push the cfg(desktop)/cfg(not(desktop)) branching
into the function body (or a plain non-command helper) instead of
cfg-gating the command function itself.
Pre-existing dead imports from fa2c1eb (Sept 11, unrelated to this PR):
TreqCommandRequest, SshEndpoint, PtyLaunchSpec, SkillInstallScope,
RemoteExecState, RemotePtyState were all imported by short name but
only ever referenced via their fully-qualified paths elsewhere in
lib.rs. verify-rust/clippy runs with warnings denied, turning these
into hard errors. CutoffReasonDto is left alone - clippy doesn't flag
it, since it's referenced by the #[tauri_test::setup] macro expansion
on TauriTestApp in the same file.
Unrelated to this PR (jj.rs last touched 2026-09-14, local_db.rs at
this branch's own base commit) - needless_borrows_for_generic_args,
iter_kv_map, and redundant_closure, all denied by verify-rust/clippy's
-D warnings. This clippy job apparently never ran to completion on
this branch before (masked by errors this PR did introduce), so these
pre-existing lints only surfaced now.
Device builds always hit 'Signing for treq_iOS requires a development
team' - xcodebuild validates automatic signing for the device SDK
before any override has a chance to apply, and --no-sign's archive
path produces the wrong artifact type. The Simulator SDK needs no
team, certificate, or provisioning profile at all, so target it
instead (--target aarch64-sim) - a genuinely unsigned build, matching
what this job is named for, without needing an Apple Developer
account.
@Ziinc
Ziinc merged commit da71f38 into main Sep 23, 2026
28 checks passed
@Ziinc
Ziinc deleted the claude/mobile-ci-workflows-audit-bthpmm branch September 23, 2026 18:39

This branch was successfully deployed

1 active deployment
preview — 757180bb Deployed Sep 23, 2026 by Ziinc via build #1220
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.

2 participants