feat(mobile): add worktree-aware debug identities - #2858
Merged
Conversation
tellaho
force-pushed
the
tho/mobile-dev-labels
branch
from
July 26, 2026 15:32
18c1d74 to
ec5390f
Compare
Mirror the desktop dev experience on mobile: debug builds produced from a
git worktree get a branch label in the app name ("Buzz (my-branch)") and a
unique app identifier, so developers can tell which worktree produced a
running iOS/Android app and keep builds from multiple worktrees installed
side by side.
- scripts/mobile-worktree-env.sh derives the label/slugs from the branch
(same worktree detection as scripts/instance-env.sh) and writes two
gitignored override files: mobile/ios/Flutter/WorktreeOverrides.xcconfig
and mobile/android/worktree.properties. In the main checkout it removes
stale overrides.
- iOS: CFBundleDisplayName now resolves from a new APP_DISPLAY_NAME build
setting; Debug.xcconfig includes WorktreeOverrides.xcconfig last so it
wins in Debug only. Release/Profile keep production identity.
- Android: the manifest label resolves from an app_name resValue; the debug
build type applies the worktree applicationIdSuffix and label from
worktree.properties. Release never reads it.
- just mobile-dev and just mobile-build-android run the script
automatically; direct Xcode/Android Studio use is documented in
mobile/README.md.
- scripts/test-mobile-worktree-env.sh covers the contract (override
generation, sanitization, debug-only wiring, gitignore) and runs in the
CI mobile-changes contract job.
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Gradle Kotlin DSL on CI resolves the lowercase `java` in `java.util.Properties()` as Gradle's `java` extension, breaking compilation of the worktree-aware debug identity block. Import the class at the top of the script and use the bare `Properties()` constructor. No behavior change; debug-only identity wiring untouched. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Address review on the worktree-aware debug identity:
- Key the install identity (bundle id / applicationIdSuffix) to the
worktree DIRECTORY name instead of the branch, so installed apps and
their login state are bounded by worktree count and never churn on
branch switches.
- Keep the branch as a display-only label, falling back to the short
SHA when the worktree is detached, and sanitize it to [A-Za-z0-9._-]
so no valid Git ref (apostrophes, quotes, $) can break Android string
resources or xcconfig values. Gradle now validates the label with the
same rigor as the suffix.
- Include WorktreeOverrides.xcconfig BEFORE AppOverrides.xcconfig so a
developer's app-specific overrides (e.g. a personal BUNDLE_IDENTIFIER
for device signing) take precedence over worktree defaults.
- Fix the release-purity contract check: the old awk /release {/,/}/
range ended at the first nested close brace and skipped most of the
release block. Replace it with a brace-counting extractor and a
self-test proving it scans past nested blocks.
- Add just mobile-clean + scripts/mobile-worktree-clean.sh to uninstall
stale worktree-suffixed installs from booted iOS simulators and
connected Android devices (--dry-run supported); production ids are
never matched.
- Rename mobile-worktree-env.sh -> mobile-worktree-overrides.sh (it
writes override files, not env), drop the hardcoded applicationId
claim from its output, and expand the contract tests: branch-switch
stability, detached HEAD, special-character refs, xcconfig precedence
order, and cleanup safety.
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
tellaho
force-pushed
the
tho/mobile-dev-labels
branch
from
July 26, 2026 16:00
ec5390f to
e140f62
Compare
tellaho
marked this pull request as ready for review
July 26, 2026 16:26
brow
approved these changes
Jul 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Category: improvement
User Impact: Developers can identify which worktree produced a mobile debug app, keep a bounded set of worktree builds installed side by side, and preserve each worktree app's login and local state while switching branches.
Problem: Mobile debug builds from every checkout currently appear as the same “Buzz” app and share one application identity, so the running source is ambiguous and one worktree build replaces another. A branch-keyed identity would avoid replacement but create stale installs and fresh app state on every branch switch.
Solution: Give each linked worktree a stable Debug-only application identity derived from its sanitized directory name. Show the sanitized branch name (or short commit SHA when detached) in the display label, persist generated native overrides for direct IDE builds, and leave Release/Profile identities unchanged. Worktree defaults remain lower precedence than a developer's iOS
AppOverrides.xcconfig.just mobile-cleanprovides a safe cleanup path for suffixed worktree installs while preserving production Buzz.File changes
.github/workflows/ci.yml
Runs the expanded worktree override contract when relevant mobile or native configuration changes.
AGENTS.md
Documents worktree-aware mobile development and cleanup for contributors and agents.
Justfile
Generates overrides before mobile development and Android debug builds, and exposes
just mobile-clean.mobile/README.md
Explains stable per-worktree identities, branch/SHA labels, direct IDE usage, cleanup, and Release/Profile guarantees.
mobile/android/.gitignore
Ignores generated worktree properties.
mobile/android/app/build.gradle.kts
Loads and validates generated properties, then applies the application ID suffix and display label to Android Debug only.
mobile/android/app/src/main/AndroidManifest.xml
Resolves the Android app label through an overridable string resource.
mobile/ios/.gitignore
Ignores generated iOS worktree settings.
mobile/ios/Flutter/Debug.xcconfig
Loads generated worktree defaults before developer
AppOverrides, so personal signing overrides retain precedence.mobile/ios/Flutter/Release.xcconfig
Pins the production display name and bundle identifier for Release/Profile builds.
mobile/ios/Runner/Info.plist
Resolves the visible iOS app name from build settings.
scripts/mobile-worktree-overrides.sh
Detects linked worktrees, derives a stable directory-keyed identity, sanitizes branch/SHA display context, writes native Debug overrides, and removes stale overrides in the main checkout.
scripts/mobile-worktree-clean.sh
Lists or removes suffixed Buzz worktree installs from booted iOS simulators and connected Android emulators without matching production IDs; supports
--dry-run.scripts/test-mobile-worktree-overrides.sh
Covers worktree detection, branch-switch identity stability, detached HEAD fallback, special-character sanitization, iOS override precedence, brace-aware Release/Profile purity, cleanup safety, ignores, and command integration.
Reproduction steps
just mobile-dev.Buzz (<sanitized-branch>), while its application ID suffix is derived from the worktree directory.AppOverrides.xcconfigand confirm developer overrides still win over generated worktree defaults.just mobile-clean --dry-run, thenjust mobile-clean, and confirm suffixed worktree installs are targeted while the production app is preserved.scripts/test-mobile-worktree-overrides.sh,just mobile-check,just mobile-test, andjust mobile-build-android.Screenshots / demos