diff --git a/.github/workflows/e2e_tests.yaml b/.github/workflows/e2e_tests.yaml index 0f5f230fc34d..76776a9779bc 100644 --- a/.github/workflows/e2e_tests.yaml +++ b/.github/workflows/e2e_tests.yaml @@ -84,15 +84,15 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 name: Xcode Compile Cache with: - key: ${{ runner.os }}-ios-v2 + key: ${{ runner.os }}-ios-v3 max-size: 700M - uses: actions/cache@v2 name: Pods Cache id: pods-cache with: path: tests/ios/Pods - key: ${{ runner.os }}-pods-v2-${{ hashFiles('tests/ios/Podfile.lock') }} - restore-keys: ${{ runner.os }}-ios-pods-v1 + key: ${{ runner.os }}-pods-v3-${{ hashFiles('tests/ios/Podfile.lock') }} + restore-keys: ${{ runner.os }}-ios-pods-v2 - name: Firebase Emulator Cache uses: actions/cache@v2 with: diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/crashlytics_add_upload_symbols b/packages/firebase_crashlytics/firebase_crashlytics/ios/crashlytics_add_upload_symbols new file mode 100755 index 000000000000..2e05e7f9fb28 --- /dev/null +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/crashlytics_add_upload_symbols @@ -0,0 +1,82 @@ +require 'xcodeproj' +require 'optparse' + +# Dictionary to hold command line arguments +options_dict = {} +options_dict[:flutter_project] = false +options_dict[:additional_options] = "" + +# Parse command line arguments into options_dict +OptionParser.new do |options| + options.banner = "Adds the Crashlytics upload-symbols tool to an Xcode target's build phase. Usage: crashlytics_upload_symbols [options]" + + options.on("-p", "--projectDirectory=DIRECTORY", String, "Directory of the Xcode project") do |dir| + options_dict[:project_dir] = dir + end + + options.on("-n", "--projectName=NAME", String, "Name of the Xcode project (ex: Runner.xcodeproj)") do |name| + options_dict[:project_name] = name + end + + options.on("-o", "--additionalOptions=OPTIONS", String, "Additional arguments to pass to upload-symbols (quote if multiple args)") do |opts| + options_dict[:additional_options] = opts + end + + options.on("-f", "--flutter", "Use flutter firebase_app_id_file.json") do |fl| + options_dict[:flutter_project] = true + end +end.parse! + +# Minimum required arguments are a project directory and project name +unless (options_dict[:project_dir] and options_dict[:project_name]) + abort("Must provide a project directory and project name.\n") +end + +# Path to the Xcode project to modify +project_path = File.join(options_dict[:project_dir], options_dict[:project_name]) + +unless (File.exist?(project_path)) + abort("Project at #{project_path} does not exist. Please check paths or incorporate Crashlytics upload symbols manually.\n"); +end + +# If this is a Flutter project, upload-symbols will use the firebase_app_id_file.json to get the app's ID. If this file doesn't exist, upload-symbols may not be +# able to upload symbols correctly. +if(options_dict[:flutter_project]) + unless File.exist?("#{options_dict[:project_dir]}/firebase_app_id_file.json") + puts("Warning: firebase_app_id_file.json file does not exist. This may cause issues in upload-symbols. If this error is unexpected, try running flutterfire configure again.") + end +end + +if(options_dict[:flutter_project]) + upload_symbols_args = "--flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" #{options_dict[:additional_options]}" +else + upload_symbols_args = options_dict[:additional_options] +end + +# Actually open and modify the project +project = Xcodeproj::Project.open(project_path) +project.targets.each do |target| + if (target.name == "Runner") + # We need to make sure that we're not adding more than one run script to upload-symbols (or overwriting custom upload-symbols scripts). + target.shell_script_build_phases().each { |phase| + if (phase.shell_script.include? "FirebaseCrashlytics/upload-symbols") + puts("Run script to upload symbols already exists.") + exit(0) + end + if (phase.shell_script.include? "FirebaseCrashlytics/run") + puts("Run script to upload symbols already exists.") + exit(0) + end + } + phase = target.shell_script_build_phases().find {|item| item.name == "[firebase_crashlytics] Crashlytics Upload Symbols"} + + # If no existing run scripts exist, then create one. + if (phase.nil?) + phase = target.new_shell_script_build_phase("[firebase_crashlytics] Crashlytics Upload Symbols") + phase.shell_script = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" #{upload_symbols_args}" + phase.input_paths = ["\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"", "\"$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)\""] + project.save() + end + end +end + diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics.podspec b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics.podspec index 79224545407d..3670f67accbd 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics.podspec +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics.podspec @@ -3,6 +3,12 @@ require 'yaml' pubspec = YAML.load_file(File.join('..', 'pubspec.yaml')) library_version = pubspec['version'].gsub('+', '-') +# Add upload-symbols script to the Flutter target. +current_dir = Dir.pwd +calling_dir = File.dirname(__FILE__) +project_dir = calling_dir.slice(0..(calling_dir.index('/.symlinks'))) +system("ruby #{current_dir}/crashlytics_add_upload_symbols -f -p #{project_dir} -n Runner.xcodeproj") + if defined?($FirebaseSDKVersion) Pod::UI.puts "#{pubspec['name']}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'" firebase_sdk_version = $FirebaseSDKVersion @@ -40,5 +46,4 @@ Pod::Spec.new do |s| 'DEFINES_MODULE' => 'YES' } s.user_target_xcconfig = { 'DEBUG_INFORMATION_FORMAT' => 'dwarf-with-dsym' } - end diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/crashlytics_add_upload_symbols b/packages/firebase_crashlytics/firebase_crashlytics/macos/crashlytics_add_upload_symbols new file mode 120000 index 000000000000..e6586b50f130 --- /dev/null +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/crashlytics_add_upload_symbols @@ -0,0 +1 @@ +../ios/crashlytics_add_upload_symbols \ No newline at end of file diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics.podspec b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics.podspec index 447fe5993fba..02e2e1422e74 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics.podspec +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics.podspec @@ -3,6 +3,16 @@ require 'yaml' pubspec = YAML.load_file(File.join('..', 'pubspec.yaml')) library_version = pubspec['version'].gsub('+', '-') +# Add upload-symbols script to the Flutter target. +current_dir = Dir.pwd +calling_dir = File.dirname(__FILE__) +project_dir = calling_dir.slice(0..(calling_dir.index('/.symlinks'))) +if project_dir.include? "Flutter/ephemeral" + # Note: macOS CWD can be based in /Flutter/ephemeral - so we need to go up two levels. + project_dir = File.expand_path(File.join(project_dir, '..', '..')) +end +system("ruby #{current_dir}/crashlytics_add_upload_symbols -f -p #{project_dir} -n Runner.xcodeproj") + if defined?($FirebaseSDKVersion) Pod::UI.puts "#{pubspec['name']}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'" firebase_sdk_version = $FirebaseSDKVersion diff --git a/tests/android/firebase_app_id_file.json b/tests/android/firebase_app_id_file.json new file mode 100644 index 000000000000..027151bb95dd --- /dev/null +++ b/tests/android/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:406099696497:android:0d4ed619c031c0ac3574d0", + "FIREBASE_PROJECT_ID": "flutterfire-e2e-tests", + "GCM_SENDER_ID": "406099696497" +} \ No newline at end of file diff --git a/tests/ios/Runner.xcodeproj/project.pbxproj b/tests/ios/Runner.xcodeproj/project.pbxproj index d7d64a671297..a2947fd4def9 100644 --- a/tests/ios/Runner.xcodeproj/project.pbxproj +++ b/tests/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -76,7 +76,6 @@ 56B65A6814148F63F80E1BCD /* Pods-Runner.release.xcconfig */, A3CCB64392E4AE128B41755D /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -141,6 +140,7 @@ 3B06AD1E1E4923F5004D2608 /* Thin Binary */, AC660AAB7696B4DD121B84D0 /* [CP] Embed Pods Frameworks */, AFACAC31EEE064D50881C495 /* [CP] Copy Pods Resources */, + 5F39B4E393588B005ADEE74A /* [firebase_crashlytics] Crashlytics Upload Symbols */, ); buildRules = ( ); @@ -213,6 +213,26 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 5F39B4E393588B005ADEE74A /* [firebase_crashlytics] Crashlytics Upload Symbols */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"", + "\"$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)\"", + ); + name = "[firebase_crashlytics] Crashlytics Upload Symbols"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" "; + }; 73AF29AE49A9551E6E30720C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/tests/ios/firebase_app_id_file.json b/tests/ios/firebase_app_id_file.json new file mode 100644 index 000000000000..cbd176455eae --- /dev/null +++ b/tests/ios/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:406099696497:ios:acd9c8e17b5e620e3574d0", + "FIREBASE_PROJECT_ID": "flutterfire-e2e-tests", + "GCM_SENDER_ID": "406099696497" +} \ No newline at end of file diff --git a/tests/lib/firebase_default_options.dart b/tests/lib/firebase_options.dart similarity index 84% rename from tests/lib/firebase_default_options.dart rename to tests/lib/firebase_options.dart index c41f8e0c4ff2..191948500928 100644 --- a/tests/lib/firebase_default_options.dart +++ b/tests/lib/firebase_options.dart @@ -1,5 +1,5 @@ // File generated by FlutterFire CLI. -// ignore_for_file: lines_longer_than_80_chars +// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb, TargetPlatform; @@ -8,7 +8,7 @@ import 'package:flutter/foundation.dart' /// /// Example: /// ```dart -/// import 'firebase_default_options.dart'; +/// import 'firebase_options.dart'; /// // ... /// await Firebase.initializeApp( /// options: DefaultFirebaseOptions.currentPlatform, @@ -19,7 +19,6 @@ class DefaultFirebaseOptions { if (kIsWeb) { return web; } - // ignore: missing_enum_constant_in_switch switch (defaultTargetPlatform) { case TargetPlatform.android: return android; @@ -27,11 +26,11 @@ class DefaultFirebaseOptions { return ios; case TargetPlatform.macOS: return macos; + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); } - - throw UnsupportedError( - 'DefaultFirebaseOptions are not supported for this platform.', - ); } static const FirebaseOptions web = FirebaseOptions( @@ -43,6 +42,7 @@ class DefaultFirebaseOptions { databaseURL: 'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app', storageBucket: 'flutterfire-e2e-tests.appspot.com', + measurementId: 'G-JN95N1JV2E', ); static const FirebaseOptions android = FirebaseOptions( @@ -63,6 +63,8 @@ class DefaultFirebaseOptions { databaseURL: 'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app', storageBucket: 'flutterfire-e2e-tests.appspot.com', + androidClientId: + '406099696497-tvtvuiqogct1gs1s6lh114jeps7hpjm5.apps.googleusercontent.com', iosClientId: '406099696497-taeapvle10rf355ljcvq5dt134mkghmp.apps.googleusercontent.com', iosBundleId: 'io.flutter.plugins.firebase.tests', @@ -76,6 +78,8 @@ class DefaultFirebaseOptions { databaseURL: 'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app', storageBucket: 'flutterfire-e2e-tests.appspot.com', + androidClientId: + '406099696497-tvtvuiqogct1gs1s6lh114jeps7hpjm5.apps.googleusercontent.com', iosClientId: '406099696497-taeapvle10rf355ljcvq5dt134mkghmp.apps.googleusercontent.com', iosBundleId: 'io.flutter.plugins.firebase.tests', diff --git a/tests/lib/main.dart b/tests/lib/main.dart index 7e78b3bf2969..acd4b0f1bf45 100644 --- a/tests/lib/main.dart +++ b/tests/lib/main.dart @@ -1,7 +1,7 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; -import 'firebase_default_options.dart'; +import 'firebase_options.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/tests/macos/Runner.xcodeproj/project.pbxproj b/tests/macos/Runner.xcodeproj/project.pbxproj index fbb663041941..b7908a6804dd 100644 --- a/tests/macos/Runner.xcodeproj/project.pbxproj +++ b/tests/macos/Runner.xcodeproj/project.pbxproj @@ -94,7 +94,6 @@ 16E3DE49D099A914502EAEAC /* Pods-Runner.release.xcconfig */, F2588DFC05D5B5F41376BEBC /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -186,6 +185,7 @@ 3399D490228B24CF009A79C7 /* ShellScript */, B6FDA406E9A0EB363B9CC88C /* [CP] Embed Pods Frameworks */, 741DA0581CD7F52CFA7F2590 /* [CP] Copy Pods Resources */, + 76D37D3A2A5275D5E0B8B1B9 /* [firebase_crashlytics] Crashlytics Upload Symbols */, ); buildRules = ( ); @@ -331,6 +331,26 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 76D37D3A2A5275D5E0B8B1B9 /* [firebase_crashlytics] Crashlytics Upload Symbols */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}\"", + "\"$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)\"", + ); + name = "[firebase_crashlytics] Crashlytics Upload Symbols"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" "; + }; B6FDA406E9A0EB363B9CC88C /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -565,6 +585,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/tests/macos/firebase_app_id_file.json b/tests/macos/firebase_app_id_file.json new file mode 100644 index 000000000000..cbd176455eae --- /dev/null +++ b/tests/macos/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:406099696497:ios:acd9c8e17b5e620e3574d0", + "FIREBASE_PROJECT_ID": "flutterfire-e2e-tests", + "GCM_SENDER_ID": "406099696497" +} \ No newline at end of file