Skip to content

Commit 4583328

Browse files
authored
Fix copyRootGoogleServices task (#5895)
Per [b/322356188](https://b.corp.google.com/issues/322356188), This fixes the issues with the `copyRootGoogleServices` task. Namely, it seems there are various tasks in the pipeline that have _implicit_ dependencies on source files- which gradle doesn't like. To fix this, we just ensure `copyRootGoogleServices` is set as a dependency of them all. This PR also moves the `copyRootGoogleServices` task into our android library plugin- to keep everything together.
1 parent 5c3f7ef commit 4583328

File tree

21 files changed

+135
-176
lines changed

21 files changed

+135
-176
lines changed

appcheck/firebase-appcheck-debug-testing/firebase-appcheck-debug-testing.gradle

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
plugins {
1616
id 'firebase-library'
17+
id 'copy-google-services'
1718
}
1819

1920
firebaseLibrary {
@@ -72,10 +73,3 @@ dependencies {
7273
androidTestImplementation 'junit:junit:4.13-beta-2'
7374
androidTestImplementation 'org.mockito:mockito-core:2.25.0'
7475
}
75-
76-
// ==========================================================================
77-
// Copy from here down if you want to use the google-services plugin in your
78-
// androidTest integration tests.
79-
// ==========================================================================
80-
ext.packageName = "com.google.firebase.appcheck.debug.testing"
81-
apply from: '../../gradle/googleServices.gradle'

appcheck/firebase-appcheck/test-app/test-app.gradle

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
apply plugin: 'com.android.application'
1616
apply plugin: 'com.google.gms.google-services'
17+
apply plugin: 'copy-google-services'
1718

1819
android {
1920
compileSdkVersion project.compileSdkVersion
@@ -45,10 +46,3 @@ dependencies {
4546
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
4647
implementation 'com.google.android.gms:play-services-tasks:18.0.1'
4748
}
48-
49-
// ==========================================================================
50-
// Copy from here down if you want to use the google-services plugin in your
51-
// androidTest integration tests.
52-
// ==========================================================================
53-
ext.packageName = "com.googletest.firebase.appcheck"
54-
apply from: '../../../gradle/googleServices.gradle'

buildSrc/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ gradlePlugin {
9494
id = "firebase-vendor"
9595
implementationClass = "com.google.firebase.gradle.plugins.VendorPlugin"
9696
}
97+
register("copyGoogleServicesPlugin") {
98+
id = "copy-google-services"
99+
implementationClass = "com.google.firebase.gradle.plugins.CopyGoogleServicesPlugin"
100+
}
97101
}
98102
}
99103

buildSrc/src/main/java/com/google/firebase/gradle/plugins/BaseFirebaseLibraryPlugin.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.firebase.gradle.plugins
1818

19+
import com.android.build.gradle.LibraryExtension
1920
import com.google.firebase.gradle.plugins.ci.Coverage
2021
import java.io.File
2122
import java.nio.file.Paths
@@ -31,6 +32,7 @@ import org.gradle.kotlin.dsl.apply
3132
import org.gradle.kotlin.dsl.configure
3233
import org.gradle.kotlin.dsl.create
3334
import org.gradle.kotlin.dsl.findByType
35+
import org.gradle.kotlin.dsl.getByType
3436
import org.gradle.kotlin.dsl.provideDelegate
3537
import org.gradle.kotlin.dsl.register
3638
import org.w3c.dom.Element
@@ -280,3 +282,19 @@ val FirebaseLibraryExtension.latestVersion: ModuleVersion
280282
"Invalid format for ModuleVersion for module '$artifactName':\n $latestVersion"
281283
)
282284
}
285+
286+
/**
287+
* Fetches the namespace for this SDK from the [LibraryExtension].
288+
*
289+
* eg;
290+
*
291+
* ```
292+
* com.googletest.firebase.appdistribution
293+
* ```
294+
*
295+
* @throws RuntimeException when the project doesn't have a defined namespace
296+
*/
297+
val FirebaseLibraryExtension.namespace: String
298+
get() =
299+
project.extensions.getByType<LibraryExtension>().namespace
300+
?: throw RuntimeException("Project doesn't have a defined namespace: ${project.path}")
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.gradle.plugins
18+
19+
import com.android.build.gradle.BaseExtension
20+
import java.io.File
21+
import org.gradle.api.Plugin
22+
import org.gradle.api.Project
23+
import org.gradle.api.tasks.Copy
24+
import org.gradle.kotlin.dsl.getByType
25+
import org.gradle.kotlin.dsl.register
26+
27+
/**
28+
* Copies the root google-services.json into the project directory during build time.
29+
*
30+
* If a path is provided via `FIREBASE_GOOGLE_SERVICES_PATH`, that will be used instead. The file
31+
* will also be renamed to `google-services.json`, so provided files do *not* need to be properly
32+
* named.
33+
*
34+
* Will also register the `com.google.gms.google-services` plugin if a test task is running.
35+
*/
36+
abstract class CopyGoogleServicesPlugin : Plugin<Project> {
37+
override fun apply(project: Project) {
38+
val copyRootGoogleServices = registerCopyRootGoogleServicesTask(project)
39+
40+
project.allprojects {
41+
// fixes dependencies with gradle tasks that do not properly dependOn `preBuild`
42+
tasks.configureEach {
43+
if (name !== "copyRootGoogleServices") dependsOn(copyRootGoogleServices)
44+
}
45+
}
46+
47+
if (project.isRunningTestTask()) {
48+
println("[test] applying google-services plugin")
49+
project.plugins.apply("com.google.gms.google-services")
50+
}
51+
}
52+
53+
private fun Project.isRunningTestTask(): Boolean {
54+
val testTasks = listOf("AndroidTest", "connectedCheck", "deviceCheck")
55+
56+
return gradle.startParameter.taskNames.any { testTasks.any(it::contains) }
57+
}
58+
59+
private fun registerCopyRootGoogleServicesTask(project: Project) =
60+
project.tasks.register<Copy>("copyRootGoogleServices") {
61+
val sourcePath =
62+
System.getenv("FIREBASE_GOOGLE_SERVICES_PATH") ?: "${project.rootDir}/google-services.json"
63+
64+
val library = project.extensions.getByType<BaseExtension>()
65+
66+
val targetPackageLine = "\"package_name\": \"${library.namespace}\""
67+
val packageLineRegex = Regex("\"package_name\":\\s+\".*\"")
68+
69+
from(sourcePath)
70+
into(project.projectDir)
71+
72+
rename { "google-services.json" }
73+
74+
if (fileIsMissingPackageName(sourcePath, targetPackageLine)) {
75+
/**
76+
* Modifies `google-services.json` such that all declared `package_name` entries are
77+
* replaced with the project's namespace. This tricks the google services plugin into
78+
* thinking that the target `package_name` is a Firebase App and allows connection to the
79+
* Firebase project.
80+
*
81+
* Note that all events generated from that app will then go to whatever the first client
82+
* entry is in the `google-services.json` file.
83+
*/
84+
filter { it.replace(packageLineRegex, targetPackageLine) }
85+
}
86+
}
87+
88+
private fun fileIsMissingPackageName(path: String, targetPackageLine: String): Boolean {
89+
val file = File(path)
90+
if (!file.exists()) return true
91+
92+
return !file.readText().contains(targetPackageLine)
93+
}
94+
}

buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import org.gradle.kotlin.dsl.register
3636
import org.gradle.kotlin.dsl.withType
3737
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
3838

39+
// TODO() maybe rename to FirebaseAndroidLibraryPlugin; makes more sense alongside java one
3940
class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() {
4041

4142
override fun apply(project: Project) {
@@ -48,10 +49,12 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() {
4849
// reduce the likelihood of kotlin module files colliding.
4950
project.tasks.withType<KotlinCompile> {
5051
kotlinOptions.freeCompilerArgs = listOf("-module-name", kotlinModuleName(project))
52+
kotlinOptions.jvmTarget = "1.8"
5153
}
5254

5355
project.apply<DackkaPlugin>()
5456
project.apply<GitSubmodulePlugin>()
57+
5558
project.tasks.getByName("preBuild").dependsOn("updateGitSubmodules")
5659
}
5760

firebase-appdistribution/test-app/test-app.gradle

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ plugins {
1616
id 'kotlin-android'
1717
id 'com.google.gms.google-services'
1818
id 'com.google.firebase.appdistribution'
19+
id 'copy-google-services'
1920
}
2021

2122
android {
@@ -96,7 +97,3 @@ dependencies {
9697

9798
testImplementation 'junit:junit:4.13.2'
9899
}
99-
100-
// This allows the app to connect to Firebase on the CI.
101-
ext.packageName = "com.googletest.firebase.appdistribution.testapp"
102-
apply from: '../../gradle/googleServices.gradle'

firebase-config/bandwagoner/bandwagoner.gradle

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
apply plugin: 'com.android.application'
1818
apply plugin: com.google.firebase.gradle.plugins.ci.device.FirebaseTestLabPlugin
1919
apply plugin: 'org.jetbrains.kotlin.android'
20+
apply plugin: 'copy-google-services'
2021

2122
// Uncomment this line after adding a google-services.json file to the project.
2223
// apply plugin: 'com.google.gms.google-services'
@@ -112,6 +113,3 @@ dependencies {
112113
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
113114
androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.2.0'
114115
}
115-
116-
ext.packageName = "com.googletest.firebase.remoteconfig.bandwagoner"
117-
apply from: '../../gradle/googleServices.gradle'

firebase-config/test-app/test-app.gradle.kts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ plugins {
2424
id("com.google.gms.google-services")
2525
id("com.google.firebase.crashlytics")
2626
id("com.google.firebase.firebase-perf")
27+
id("copy-google-services")
2728
}
2829

2930
android {
@@ -90,8 +91,4 @@ dependencies {
9091
androidTestImplementation(libs.truth)
9192
}
9293

93-
extra["packageName"] = "com.google.firebase.testing.config"
94-
95-
apply(from = "../../gradle/googleServices.gradle")
96-
9794
apply<FirebaseTestLabPlugin>()

firebase-database/firebase-database.gradle.kts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
plugins {
1616
id("firebase-library")
1717
id("kotlin-android")
18+
id("copy-google-services")
1819
}
1920

2021
firebaseLibrary {
@@ -93,7 +94,3 @@ dependencies {
9394
androidTestImplementation(libs.quickcheck)
9495
androidTestImplementation(libs.truth)
9596
}
96-
97-
ext["packageName"] = "com.google.firebase.database"
98-
99-
apply("../gradle/googleServices.gradle")

0 commit comments

Comments
 (0)