Skip to content

Commit

Permalink
fix(android): ensure app/build.gradle only writes google services dep…
Browse files Browse the repository at this point in the history
…endency once (#269)
  • Loading branch information
russellwheatley committed Mar 25, 2024
1 parent 9c10269 commit f195b16
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 24 deletions.
Expand Up @@ -372,25 +372,27 @@ AndroidGradleContents _applyGoogleServicesPlugin(
);
}

androidAppBuildGradleFileContents = androidAppBuildGradleFileContents
.replaceFirstMapped(_androidAppBuildGradleRegex, (match) {
// Check which pattern was matched and insert the appropriate content
if (match.group(0) != null) {
if (buildGradleConfiguration == BuildGradleConfiguration.legacy2 ||
buildGradleConfiguration == BuildGradleConfiguration.latest) {
// This is legacy2 & latest
// If matched pattern is 'id "com.android.application"'
return "${match.group(0)}\n $_flutterFireConfigCommentStart\n id '$_googleServicesPluginName'\n $_flutterFireConfigCommentEnd";
} else {
// This is legacy1
// If matched pattern is 'apply plugin:...'
return "${match.group(0)}\n$_flutterFireConfigCommentStart\napply plugin: '$_googleServicesPluginName'\n$_flutterFireConfigCommentEnd";
if (!androidAppBuildGradleFileContents.contains(_googleServicesPluginName)) {
androidAppBuildGradleFileContents = androidAppBuildGradleFileContents
.replaceFirstMapped(_androidAppBuildGradleRegex, (match) {
// Check which pattern was matched and insert the appropriate content
if (match.group(0) != null) {
if (buildGradleConfiguration == BuildGradleConfiguration.legacy2 ||
buildGradleConfiguration == BuildGradleConfiguration.latest) {
// This is legacy2 & latest
// If matched pattern is 'id "com.android.application"'
return "${match.group(0)}\n $_flutterFireConfigCommentStart\n id '$_googleServicesPluginName'\n $_flutterFireConfigCommentEnd";
} else {
// This is legacy1
// If matched pattern is 'apply plugin:...'
return "${match.group(0)}\n$_flutterFireConfigCommentStart\napply plugin: '$_googleServicesPluginName'\n$_flutterFireConfigCommentEnd";
}
}
}
throw Exception(
'Could not match pattern in android/app `build.gradle` file for plugin $_googleServicesPluginName',
);
});
throw Exception(
'Could not match pattern in android/app `build.gradle` file for plugin $_googleServicesPluginName',
);
});
}

if (buildGradleConfiguration == BuildGradleConfiguration.latest) {
final pluginExists = androidGradleSettingsFileContents
Expand Down
61 changes: 61 additions & 0 deletions packages/flutterfire_cli/test/configure_test.dart
Expand Up @@ -1437,4 +1437,65 @@ void main() {
Duration(minutes: 2),
),
);

test(
'flutterfire configure: ensure android build.gradle files are only updated once',
() async {
// Add crashlytics and performance to check they are only created once
final result = Process.runSync(
'flutter',
['pub', 'add', 'firebase_crashlytics', 'firebase_performance'],
workingDirectory: projectPath,
);

if (result.exitCode != 0) {
fail(result.stderr as String);
}
// Run first time to update
Process.runSync(
'flutterfire',
[
'configure',
'--yes',
// Only android
'--platforms=android',
'--ios-bundle-id=com.example.flutterTestCli',
'--android-package-name=com.example.flutter_test_cli',
'--macos-bundle-id=com.example.flutterTestCli',
'--web-app-id=$webAppId',
'--windows-app-id=$windowsAppId',
'--project=$firebaseProjectId',
],
workingDirectory: projectPath,
runInShell: true,
);
// Run second time and check it was only updated once
final result2 = Process.runSync(
'flutterfire',
[
'configure',
'--yes',
// Only android
'--platforms=android',
'--ios-bundle-id=com.example.flutterTestCli',
'--android-package-name=com.example.flutter_test_cli',
'--macos-bundle-id=com.example.flutterTestCli',
'--web-app-id=$webAppId',
'--windows-app-id=$windowsAppId',
'--project=$firebaseProjectId',
],
workingDirectory: projectPath,
runInShell: true,
);

if (result2.exitCode != 0) {
fail(result2.stderr as String);
}

await checkBuildGradleFileUpdated(
projectPath!,
checkCrashlytics: true,
checkPerf: true,
);
});
}
24 changes: 18 additions & 6 deletions packages/flutterfire_cli/test/test_utils.dart
Expand Up @@ -438,11 +438,12 @@ Future<void> checkBuildGradleFileUpdated(
bool checkPerf = false,
bool checkCrashlytics = false,
}) async {
// Check android/settings.gradle
final androidSettingsGradlePath =
p.join(projectPath, 'android', 'settings.gradle');
final androidBuildGradle = File(androidSettingsGradlePath).readAsStringSync();

final pluginsPattern = [
final pluginsPatternSettings = [
'// START: FlutterFire Configuration',
r'id "com\.google\.gms\.google-services" version "\d+\.\d+\.\d+" apply false',
if (checkPerf)
Expand All @@ -452,18 +453,25 @@ Future<void> checkBuildGradleFileUpdated(
'// END: FlutterFire Configuration',
].join(r'\s*');

final pattern = RegExp(pluginsPattern, multiLine: true, dotAll: true);
final patternSettings =
RegExp(pluginsPatternSettings, multiLine: true, dotAll: true);

final exists = pattern.hasMatch(androidBuildGradle);
final matchesSettings = patternSettings.allMatches(androidBuildGradle);

if (!exists) {
if (matchesSettings.isEmpty) {
fail('android/settings.gradle file was not updated as expected');
} else if (matchesSettings.length > 1) {
fail(
'android/settings.gradle file contains duplicate FlutterFire configurations',
);
}

// Check android/app/build.gradle
final androidAppBuildGradlePath =
p.join(projectPath, 'android', 'app', 'build.gradle');
final androidAppBuildGradle =
File(androidAppBuildGradlePath).readAsStringSync();

final pluginsPatternApp = [
'// START: FlutterFire Configuration',
r"(apply plugin: 'com\.google\.gms\.google-services'|id 'com\.google\.gms\.google-services')",
Expand All @@ -477,10 +485,14 @@ Future<void> checkBuildGradleFileUpdated(
final patternForApp =
RegExp(pluginsPatternApp, multiLine: true, dotAll: true);

final existsForApp = patternForApp.hasMatch(androidAppBuildGradle);
final matchesForApp = patternForApp.allMatches(androidAppBuildGradle);

if (!existsForApp) {
if (matchesForApp.isEmpty) {
fail('android/app/build.gradle file was not updated as expected');
} else if (matchesForApp.length > 1) {
fail(
'android/app/build.gradle file contains duplicate FlutterFire configurations',
);
}
}

Expand Down

0 comments on commit f195b16

Please sign in to comment.