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")

firebase-firestore/firebase-firestore.gradle

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

2122
firebaseLibrary {
@@ -40,7 +41,6 @@ protobuf {
4041
}
4142
generateProtoTasks {
4243
all().each { task ->
43-
task.dependsOn("copyRootGoogleServices")
4444
task.builtins {
4545
java { option 'lite' }
4646
}
@@ -186,10 +186,3 @@ gradle.projectsEvaluated {
186186
options.compilerArgs << "-Xlint:deprecation" // << "-Werror"
187187
}
188188
}
189-
190-
// ==========================================================================
191-
// Copy from here down if you want to use the google-services plugin in your
192-
// androidTest integration tests.
193-
// ==========================================================================
194-
ext.packageName = "com.google.firebase.firestore"
195-
apply from: '../gradle/googleServices.gradle'

firebase-functions/firebase-functions.gradle.kts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ plugins {
1616
id("firebase-library")
1717
id("kotlin-android")
1818
id("firebase-vendor")
19+
id("copy-google-services")
1920
}
2021

2122
firebaseLibrary {
@@ -97,10 +98,3 @@ dependencies {
9798
androidTestImplementation(libs.mockito.dexmaker)
9899
androidTestImplementation(libs.truth)
99100
}
100-
101-
// ==========================================================================
102-
// Copy from here down if you want to use the google-services plugin in your
103-
// androidTest integration tests.
104-
// ==========================================================================
105-
extra["packageName"] = "com.google.firebase.functions"
106-
apply(from = "../gradle/googleServices.gradle")

firebase-ml-modeldownloader/firebase-ml-modeldownloader.gradle

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ plugins {
1717
id("kotlin-android")
1818
id 'firebase-vendor'
1919
id 'com.google.protobuf'
20+
id("copy-google-services")
2021
}
2122

2223
firebaseLibrary {
@@ -131,10 +132,3 @@ dependencies {
131132
androidTestImplementation "com.google.truth:truth:$googleTruthVersion"
132133
androidTestImplementation 'junit:junit:4.13.1'
133134
}
134-
135-
// ==========================================================================
136-
// Copy from here down if you want to use the google-services plugin in your
137-
// androidTest integration tests.
138-
// ==========================================================================
139-
ext.packageName = "com.google.firebase.ml.modeldownloader"
140-
apply from: '../gradle/googleServices.gradle'

firebase-perf/dev-app/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ There are differences in terms of Firebase projects when running this command in
8585
1. **CI Run**: These tests are run under Firebase Test Lab of the unified Firebase project
8686
(according to [this](https://github.com/firebase/firebase-android-sdk/blob/master/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/device/FirebaseTestServer.java))
8787
but the performance events are sent to a different project with which apps are configured with
88-
(see [this](https://github.com/firebase/firebase-android-sdk/blob/master/gradle/googleServices.gradle)).
88+
(see `copyRootGoogleServices` task).
8989

9090
1. **Local run**: When running locally both the tests and the events will happen on the same locally
9191
integrated Firebase project.

firebase-perf/dev-app/dev-app.gradle

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ apply plugin: 'com.android.application'
1616
// Firebase performance plugin, the relevant dependency is specified in the "buildSrc/build-src.gradle"
1717
apply plugin: 'com.google.firebase.firebase-perf'
1818
apply plugin: com.google.firebase.gradle.plugins.ci.device.FirebaseTestLabPlugin
19+
apply plugin: 'copy-google-services'
1920

2021
firebaseTestLab {
2122
device 'model=Pixel2,version=28,locale=en,orientation=portrait'
@@ -120,7 +121,3 @@ dependencies {
120121
androidTestImplementation 'com.google.truth:truth:1.1.2'
121122
androidTestImplementation 'com.google.truth.extensions:truth-java8-extension:1.0.1'
122123
}
123-
124-
// This allows the app to connect to Firebase on the CI.
125-
ext.packageName = "com.googletest.firebase.perf.testapp.prod"
126-
apply from: '../../gradle/googleServices.gradle'

firebase-perf/e2e-app/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ There are differences in terms of Firebase projects when running this command in
7777
1. **CI Run**: These tests are run under Firebase Test Lab of the unified Firebase project
7878
(according to [this](https://github.com/firebase/firebase-android-sdk/blob/master/buildSrc/src/main/java/com/google/firebase/gradle/plugins/ci/device/FirebaseTestServer.java))
7979
but the performance events are sent to a different project with which apps are configured with
80-
(see [this](https://github.com/firebase/firebase-android-sdk/blob/master/gradle/googleServices.gradle)
80+
(see `copyRootGoogleServices` task)
8181
and the Prow Configuration in tg/831643).
8282

8383
1. **Local run**: When running locally both the tests and the events will happen on the same locally

firebase-perf/e2e-app/e2e-app.gradle

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ apply plugin: 'com.android.application'
1616
// Firebase performance plugin, the relevant dependency is specified in the "buildSrc/build-src.gradle"
1717
apply plugin: 'com.google.firebase.firebase-perf'
1818
apply plugin: com.google.firebase.gradle.plugins.ci.device.FirebaseTestLabPlugin
19+
apply plugin: 'copy-google-services'
1920

2021
// Since Test Lab devices are wiped off immediately (for both Security and Privacy reasons) we have
2122
// previously seen issues pertaining to the App not sending data to our backend when the
@@ -112,7 +113,3 @@ dependencies {
112113
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
113114
androidTestImplementation "com.google.truth:truth:$googleTruthVersion"
114115
}
115-
116-
// This allows the app to connect to Firebase on the CI.
117-
ext.packageName = "com.google.firebase.testing.fireperf"
118-
apply from: '../../gradle/googleServices.gradle'

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

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

3031
android {
@@ -96,10 +97,6 @@ dependencies {
9697
androidTestImplementation(libs.truth)
9798
}
9899

99-
extra["packageName"] = "com.google.firebase.testing.sessions"
100-
101-
apply(from = "../../gradle/googleServices.gradle")
102-
103100
apply<FirebaseTestLabPlugin>()
104101

105102
configure<FirebaseTestLabExtension> {

0 commit comments

Comments
 (0)