invertase / flutterfire_cli

A CLI to help with using FlutterFire in your Flutter applications.
Apache License 2.0
164 stars 47 forks source link

[bug]: `google-services.json` not found when location specified with `--android-out` parameter #316

Closed Cyrille-Dakhlia closed 3 days ago

Cyrille-Dakhlia commented 1 week ago

Is there an existing issue for this?

CLI Version

1.0.0

Firebase Tools version

13.11.2

Flutter Doctor Output

flutter doctor -v [✓] Flutter (Channel stable, 3.22.2, on macOS 14.5 23F79 darwin-arm64, locale en-GB) • Flutter version 3.22.2 on channel stable at /Users/cyrilledakhlia/Development/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 761747bfc5 (13 days ago), 2024-06-05 22:15:13 +0200 • Engine revision edd8546116 • Dart version 3.4.3 • DevTools version 2.34.3

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/cyrilledakhlia/Library/Android/sdk • Platform android-34, build-tools 34.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314) • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15E204a • CocoaPods version 1.15.2

[✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.1) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)

[✓] VS Code (version 1.90.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.90.0

[✓] Connected device (4 available) • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 14 (API 34) (emulator) • macOS (desktop) • macos • darwin-arm64 • macOS 14.5 23F79 darwin-arm64 • Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin • macOS 14.5 23F79 darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 126.0.6478.61

[✓] Network resources • All expected network resources are available.

• No issues found!


Description

TL;DR: After running flutterfire configure with this parameter and its value --android-out=android/app/firebase/flavors/staging/google-services.json , running the staging version of my app on an Android emulator gives me the following error:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:processStagingDebugGoogleServices'.
> File google-services.json is missing. The Google Services Plugin cannot function without it. 
   Searched Location: 
  /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/staging/debug/google-services.json
  /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/debug/staging/google-services.json
  /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/staging/google-services.json
  /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/debug/google-services.json
  /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/stagingDebug/google-services.json
  /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/google-services.json
2

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 3s
Error: Gradle task assembleStagingDebug failed with exit code 1

Exited (1).

-> The Gradle task does not search the google-services.json file where I specified it


DETAILED DESCRIPTION:

        flutterfire configure \
            --project=<redacted> \
            --out=lib/firebase/firebase_options_staging.dart \
            --android-package-name=<redacted> \
            --android-out=android/app/firebase/flavors/staging/google-services.json \
            --ios-bundle-id=<redacted> \
            --ios-out=ios/firebase/flavors/staging/GoogleService-Info.plist \
            --ios-build-config=Debug-staging,Profile-staging,Release-staging
        flutterfire configure \
            --project=<redacted> \
            --out=lib/firebase/firebase_options_production.dart \
            --android-package-name=<redacted> \
            --android-out=android/app/firebase/flavors/production/google-services.json \
            --ios-bundle-id=<redacted> \
            --ios-out=ios/firebase/flavors/production/GoogleService-Info.plist \
            --ios-build-config=Debug-production,Profile-production,Release-production

import 'package:flutter/services.dart'; import 'firebase/firebase_options_production.dart' as production; import 'firebase/firebase_options_staging.dart' as staging; import 'package:firebase_core/firebase_core.dart';

enum Flavor { production(envFilePath: 'env/production.env'), staging(envFilePath: 'env/staging.env');

final String envFilePath;

const Flavor({required this.envFilePath}); }

Flavor getFlavor() => switch (appFlavor) { 'production' => Flavor.production, 'staging' => Flavor.staging, _ => throw UnsupportedError( 'Invalid flavor: "$appFlavor". Please specify one of the following flavors: "production", "staging" (flutter run --flavor staging).'), };

Future initializeFirebaseApp() async { final firebaseOptions = switch (getFlavor()) { Flavor.production => production.DefaultFirebaseOptions.currentPlatform, Flavor.staging => staging.DefaultFirebaseOptions.currentPlatform, }; await Firebase.initializeApp(options: firebaseOptions); }

- Running the `flutterfire configure` commands previously mentioned produced the creation of the following `firebase.json` file:
```json
{
    "flutter": {
        "platforms": {
            "android": {
                "buildConfigurations": {
                    "firebase/flavors/staging": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "fileOutput": "android/app/firebase/flavors/staging/google-services.json"
                    },
                    "firebase/flavors/production": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "fileOutput": "android/app/firebase/flavors/production/google-services.json"
                    }
                }
            },
            "ios": {
                "buildConfigurations": {
                    "Debug-staging": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "uploadDebugSymbols": false,
                        "fileOutput": "ios/firebase/flavors/staging/GoogleService-Info.plist"
                    },
                    "Profile-staging": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "uploadDebugSymbols": false,
                        "fileOutput": "ios/firebase/flavors/staging/GoogleService-Info.plist"
                    },
                    "Release-staging": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "uploadDebugSymbols": false,
                        "fileOutput": "ios/firebase/flavors/staging/GoogleService-Info.plist"
                    },
                    "Debug-production": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "uploadDebugSymbols": false,
                        "fileOutput": "ios/firebase/flavors/production/GoogleService-Info.plist"
                    },
                    "Profile-production": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "uploadDebugSymbols": false,
                        "fileOutput": "ios/firebase/flavors/production/GoogleService-Info.plist"
                    },
                    "Release-production": {
                        "projectId": "<redacted>",
                        "appId": "<redacted>",
                        "uploadDebugSymbols": false,
                        "fileOutput": "ios/firebase/flavors/production/GoogleService-Info.plist"
                    }
                }
            },
            "dart": {
                "lib/firebase/firebase_options_staging.dart": {
                    "projectId": "<redacted>",
                    "configurations": {
                        "android": "<redacted>",
                        "ios": "<redacted>",
                        "web": "<redacted>"
                    }
                },
                "lib/firebase/firebase_options_production.dart": {
                    "projectId": "<redacted>",
                    "configurations": {
                        "android": "<redacted>",
                        "ios": "<redacted>",
                        "web": "<redacted>"
                    }
                }
            }
        }
    }
}

So I can see that the --android-out=android/app/firebase/flavors/staging/google-services.json parameter I specified when running the flutterfire command was taken into account as it has it is mentioned in the firebase.json file.

BUILD FAILED in 3s Error: Gradle task assembleStagingDebug failed with exit code 1

Exited (1).

-> I can see that the Gradle task does not search the `google-services.json` file where I specified it.

---

### Steps to reproduce

1. Have a Flutter project configured with flavours (`staging`, `production`) (this step may be optional, but I cannot say for sure, see *"Hypothetical short steps to reproduce"* section below)
2. Have a Firebase project for the `staging` and `production` versions of the Flutter app (you could only do this for the `staging` version to avoid duplicating the work, in this case, remove all the further tasks related to the `production` version of the app)
3. Configure Firebase in the Flutter project for the `staging` and `production` versions of the app:
```shell
        flutterfire configure \
            --project=<redacted> \
            --out=lib/firebase/firebase_options_staging.dart \
            --android-package-name=<redacted> \
            --android-out=android/app/firebase/flavors/staging/google-services.json \
            --ios-bundle-id=<redacted> \
            --ios-out=ios/firebase/flavors/staging/GoogleService-Info.plist \
            --ios-build-config=Debug-staging,Profile-staging,Release-staging
        flutterfire configure \
            --project=<redacted> \
            --out=lib/firebase/firebase_options_production.dart \
            --android-package-name=<redacted> \
            --android-out=android/app/firebase/flavors/production/google-services.json \
            --ios-bundle-id=<redacted> \
            --ios-out=ios/firebase/flavors/production/GoogleService-Info.plist \
            --ios-build-config=Debug-production,Profile-production,Release-production
  1. Change main.dart and add a flavor_config.dart file like so:
    // main.dart file
    ...
    void main() async {
    ...
    WidgetsFlutterBinding.ensureInitialized();
    await initializeFirebaseApp();
    ...
    }
    
    // flavor_config.dart file

import 'package:flutter/services.dart'; import 'firebase/firebase_options_production.dart' as production; import 'firebase/firebase_options_staging.dart' as staging; import 'package:firebase_core/firebase_core.dart';

enum Flavor { production, staging }

Flavor getFlavor() => switch (appFlavor) { // This appFlavor variable comes from package:flutter/services.dart 'production' => Flavor.production, 'staging' => Flavor.staging, _ => throw UnsupportedError( 'Invalid flavor: "$appFlavor". Please specify one of the following flavors: "production", "staging" (flutter run --flavor staging).'), };

Future initializeFirebaseApp() async { final firebaseOptions = switch (getFlavor()) { Flavor.production => production.DefaultFirebaseOptions.currentPlatform, Flavor.staging => staging.DefaultFirebaseOptions.currentPlatform, }; await Firebase.initializeApp(options: firebaseOptions); }

5. Add `firebase_core` to your project: `flutter pub add firebase_core` (I have version `3.1.0`)
6. Run the staging version of the app on an Android simulator: `flutter run --flavor staging`
7. Notice the run failure and the output log in the console:

FAILURE: Build failed with an exception.

BUILD FAILED in 3s Error: Gradle task assembleStagingDebug failed with exit code 1

Exited (1).


---

**"Hypothetical short steps to reproduce"**
Flavours may not be required to reproduce this if specifying a location for `google-services.json` file, via the `--android-out` parameter of the `flutterfire command`, is enough to notice if the Gradle task `:app:process(Staging)DebugGoogleServices` does not look for the `google-services.json` file in the location we specified

---

### Expected behavior

When running the staging version of my app on an Android emulator, I expected the `google-services.json` file to be found at the location I specified.

Path I specified:

android/app/firebase/flavors/staging/google-services.json


Path where it was searched for:

Execution failed for task ':app:processStagingDebugGoogleServices'.

File google-services.json is missing. The Google Services Plugin cannot function without it. Searched Location: /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/staging/debug/google-services.json /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/debug/staging/google-services.json /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/staging/google-services.json /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/debug/google-services.json /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/src/stagingDebug/google-services.json /Users/cyrilledakhlia/Development/Projects/research_protocol_frontend/android/app/google-services.json


Screenshots

No response

Additional context and comments

No response

russellwheatley commented 3 days ago

See documentation for what is valid in terms of placing your google-services.json file: https://developers.google.com/android/guides/google-services-plugin#adding_the_json_file

If any of the directories containing the google-services.json file are not a build type or flavor, you're going to have a problem.

I imagine looking at this that firebase & flavors are unnecessary directories: android/app/firebase/flavors/staging/google-services.json

This isn't something we have control over, it is just how the google services plugin works.