From 4ef0a51c6a0ab3ac725dedca0e76cb8e5a9caf77 Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Tue, 13 Oct 2026 15:53:04 -0400 Subject: [PATCH] Add :nostore build scripts that disable Firebase for one Android or iOS build without changing the Firebase-on default. --- AGENTS.md | 4 ++-- BUILDING.md | 9 ++++++++- doc/android-firebase-gms.md | 10 ++++++---- package.json | 10 ++++++++++ 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c07aab7a..51f6d292 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,9 +7,9 @@ `android/app/google-services.json` is required when Firebase is enabled. It does not decide the switch: a missing file fails the build, and a file on disk is ignored when Firebase is explicitly disabled. - **Default (local, test, production, Play Store)**: `./gradlew assembleRelease` or `./gradlew bundleRelease` — do not pass `-PfirebaseEnabled`. -- **Opt out (F-Droid / FOSS)**: `./gradlew assembleRelease -PfirebaseEnabled=false`. npm scripts honor `FIREBASE_ENABLED=false`, which forwards that property. +- **Opt out (F-Droid / FOSS)**: `./gradlew assembleRelease -PfirebaseEnabled=false`, or an npm `:nostore` script such as `npm run build:android:test:nostore:run`. Those set `FIREBASE_ENABLED=false`, which forwards `-PfirebaseEnabled=false`. `:nostore` disables Firebase only; it does not remove every Play Services dependency. -iOS builds bundle `ios/App/App/GoogleService-Info.plist` by default (`ios/App/scripts/bundle-firebase-config.sh`, run from `scripts/build-ios.sh` and as an Xcode build phase). Opt out with `FIREBASE_ENABLED=false` (the build script forwards that to xcodebuild) or the Xcode build setting `FIREBASE_ENABLED=NO`. A missing plist fails an enabled build; the file's presence does not enable Firebase on its own. +iOS builds bundle `ios/App/App/GoogleService-Info.plist` by default (`ios/App/scripts/bundle-firebase-config.sh`, run from `scripts/build-ios.sh` and as an Xcode build phase). Opt out with `FIREBASE_ENABLED=false` (the build script forwards that to both the build and archive `xcodebuild` invocations), `npm run build:ios:prod:nostore`, or the Xcode build setting `FIREBASE_ENABLED=NO`. A missing plist fails an enabled build; the file's presence does not enable Firebase on its own. The guard is in `android/app/build.gradle`. Do NOT activate Firebase from file presence alone — that was the bug that broke FOSS distribution in June 2026. diff --git a/BUILDING.md b/BUILDING.md index 561e488c..27766505 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1074,6 +1074,9 @@ npm run build:ios:prod # Production build (builds for production en npm run build:ios:test:run # Test build with auto-run (builds then runs on simulator) npm run build:ios:prod:run # Production build with auto-run (builds then runs on simulator) +# Firebase off (`:nostore` sets FIREBASE_ENABLED=false, forwarded to xcodebuild as FIREBASE_ENABLED=NO) +npm run build:ios:prod:nostore # Same as prod, without Firebase + # Debug and release builds npm run build:ios:debug # Debug build (builds debug app bundle) npm run build:ios:debug:run # Debug build with auto-run (builds then runs on simulator) @@ -1337,6 +1340,10 @@ npm run build:android:test:run # Test build with auto-run (builds then run npm run build:android:prod:run # Production build with auto-run (builds then runs on emulator) # Auto-run targets the one connected device; with none or several it prompts, or exits 9 without a terminal +# Firebase off (`:nostore` sets FIREBASE_ENABLED=false, which passes -PfirebaseEnabled=false) +npm run build:android:test:nostore:run # Same as test:run, without Firebase +npm run build:android:prod:nostore # Same as prod, without Firebase + # Debug and release builds npm run build:android:debug # Debug build (builds debug APK) npm run build:android:debug:run # Debug build with auto-run (builds then runs on emulator) @@ -1476,7 +1483,7 @@ To create a signed `aab` release: ./gradlew bundleRelease -Dlint.baselines.continue=true ``` -Firebase is on by default (`firebaseEnabled=true` in `android/gradle.properties`). Do not pass `-PfirebaseEnabled` for a normal release. F-Droid and other builds that must omit Firebase use `-PfirebaseEnabled=false`. +Firebase is on by default (`firebaseEnabled=true` in `android/gradle.properties`). Do not pass `-PfirebaseEnabled` for a normal release. F-Droid and other builds that must omit Firebase use `-PfirebaseEnabled=false`, or an npm `:nostore` script (`FIREBASE_ENABLED=false`). `:nostore` only disables Firebase. It does not remove other store-linked dependencies, such as the ML Kit barcode scanner's Play Services library, and it does not by itself make the app run on every device outside the Play Store. ... and find your `aab` file at app/build/outputs/bundle/release diff --git a/doc/android-firebase-gms.md b/doc/android-firebase-gms.md index b6de160d..c3aa14f3 100644 --- a/doc/android-firebase-gms.md +++ b/doc/android-firebase-gms.md @@ -10,9 +10,11 @@ The app is designed to work on Android devices with and without Google Play Serv When Firebase is on, `android/app/google-services.json` must exist, be non-empty, and contain `mobilesdk_app_id`. Otherwise configuration fails with an error that names that path. When Firebase is off, the file is ignored even if it is on disk. -`scripts/build-android.sh` forwards an opt-out: `FIREBASE_ENABLED=false` adds `-PfirebaseEnabled=false` to its Gradle commands. npm scripts do not pass `-PfirebaseEnabled`; they rely on the default. +`scripts/build-android.sh` forwards an opt-out: `FIREBASE_ENABLED=false` adds `-PfirebaseEnabled=false` to its Gradle commands. Default npm scripts leave Firebase on. A `:nostore` script sets `FIREBASE_ENABLED=false` and reuses that script (`npm run build:android:test:nostore:run`). -iOS uses the same default. `ios/App/scripts/bundle-firebase-config.sh` copies `ios/App/App/GoogleService-Info.plist` into the app and the share extension. `scripts/build-ios.sh` runs it with `--check` before a device build, and both Xcode targets run it as a build phase. `FIREBASE_ENABLED=false` skips the plist. A missing or empty plist fails the build when Firebase is on. +iOS uses the same default. `ios/App/scripts/bundle-firebase-config.sh` copies `ios/App/App/GoogleService-Info.plist` into the app and the share extension. `scripts/build-ios.sh` runs it with `--check` before a device build, and both Xcode targets run it as a build phase. The build and archive `xcodebuild` commands both receive `FIREBASE_ENABLED`. `FIREBASE_ENABLED=false` becomes `FIREBASE_ENABLED=NO` and skips the plist. A `:nostore` script sets that variable (`npm run build:ios:prod:nostore`). A missing or empty plist fails the build when Firebase is on. + +`:nostore` disables Firebase only. It does not strip other store-linked dependencies (the ML Kit barcode scanner still pulls in Play Services) and does not guarantee the build will run on every device outside the Play Store. ## Build commands @@ -21,8 +23,8 @@ iOS uses the same default. `ios/App/scripts/bundle-firebase-config.sh` copies `i | Local / test / production APK or AAB | `./gradlew assembleRelease` or `bundleRelease` | on | | Play Store with FCM | `./gradlew bundleRelease` | on | | iOS (Xcode or `scripts/build-ios.sh`) | default | on | -| F-Droid / FOSS Android | `./gradlew assembleRelease -PfirebaseEnabled=false` | off | -| iOS without Firebase | `FIREBASE_ENABLED=false` | off | +| F-Droid / FOSS Android | `./gradlew assembleRelease -PfirebaseEnabled=false` or `npm run build:android:test:nostore` | off | +| iOS without Firebase | `FIREBASE_ENABLED=false` or `npm run build:ios:prod:nostore` | off | ## Behavior on non-GMS devices diff --git a/package.json b/package.json index a97aa8f4..78ecb588 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,11 @@ "build:android:deploy": "./scripts/build-android.sh --deploy", "build:android:dev": "./scripts/build-android.sh --dev", "build:android:dev:custom": "./scripts/build-android.sh --dev --api-ip", + "build:android:dev:nostore": "FIREBASE_ENABLED=false npm run build:android:dev", "build:android:dev:run:custom": "./scripts/build-android.sh --dev --api-ip --auto-run", "build:android:prod": "./scripts/build-android.sh --prod", + "build:android:prod:nostore": "FIREBASE_ENABLED=false npm run build:android:prod", + "build:android:prod:nostore:run": "FIREBASE_ENABLED=false npm run build:android:prod:run", "build:android:prod:run": "./scripts/build-android.sh --prod --auto-run", "build:android:release": "./scripts/build-android.sh --release", "build:android:release:run": "./scripts/build-android.sh --release --auto-run", @@ -35,6 +38,8 @@ "build:android:sync": "./scripts/build-android.sh --sync", "build:android:test": "./scripts/build-android.sh --test", "build:android:test:custom": "./scripts/build-android.sh --test --api-ip", + "build:android:test:nostore": "FIREBASE_ENABLED=false npm run build:android:test", + "build:android:test:nostore:run": "FIREBASE_ENABLED=false npm run build:android:test:run", "build:android:test:run": "./scripts/build-android.sh --test --auto-run", "build:android:test:run:custom": "./scripts/build-android.sh --test --api-ip --auto-run", "build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts", @@ -78,9 +83,12 @@ "build:ios:deploy": "./scripts/build-ios.sh --deploy", "build:ios:dev": "./scripts/build-ios.sh --dev", "build:ios:dev:custom": "./scripts/build-ios.sh --dev --api-ip", + "build:ios:dev:nostore": "FIREBASE_ENABLED=false npm run build:ios:dev", "build:ios:dev:run:custom": "./scripts/build-ios.sh --dev --api-ip --auto-run", "build:ios:ipa": "./scripts/build-ios.sh --ipa", "build:ios:prod": "./scripts/build-ios.sh --prod", + "build:ios:prod:nostore": "FIREBASE_ENABLED=false npm run build:ios:prod", + "build:ios:prod:nostore:run": "FIREBASE_ENABLED=false npm run build:ios:prod:run", "build:ios:prod:run": "./scripts/build-ios.sh --prod --auto-run", "build:ios:release": "./scripts/build-ios.sh --release", "build:ios:release:run": "./scripts/build-ios.sh --release --auto-run", @@ -88,6 +96,8 @@ "build:ios:sync": "./scripts/build-ios.sh --sync", "build:ios:test": "./scripts/build-ios.sh --test", "build:ios:test:custom": "./scripts/build-ios.sh --test --api-ip", + "build:ios:test:nostore": "FIREBASE_ENABLED=false npm run build:ios:test", + "build:ios:test:nostore:run": "FIREBASE_ENABLED=false npm run build:ios:test:run", "build:ios:test:run": "./scripts/build-ios.sh --test --auto-run", "build:ios:test:run:custom": "./scripts/build-ios.sh --test --api-ip --auto-run", "build:native": "npm run build:capacitor:sync && bash -c 'source scripts/common.sh && ensure_ios_capacitor_asset_directories' && npx capacitor-assets generate --ios --android --assetPath resources",