Merge branch 'main' into ci/androidTest

pull/570/head
Simon Marquis 2 years ago
commit 69a2634f0c

@ -47,7 +47,7 @@ android {
missingDimensionStrategy(FlavorDimension.contentType.name, NiaFlavor.demo.name) missingDimensionStrategy(FlavorDimension.contentType.name, NiaFlavor.demo.name)
} }
packagingOptions { packaging {
resources { resources {
excludes.add("/META-INF/{AL2.0,LGPL2.1}") excludes.add("/META-INF/{AL2.0,LGPL2.1}")
} }
@ -55,7 +55,7 @@ android {
namespace = "com.google.samples.apps.niacatalog" namespace = "com.google.samples.apps.niacatalog"
buildTypes { buildTypes {
val release by getting { release {
// To publish on the Play store a private signing key is required, but to allow anyone // To publish on the Play store a private signing key is required, but to allow anyone
// who clones the code to sign and run the release variant, use the debug signing key. // who clones the code to sign and run the release variant, use the debug signing key.
// TODO: Abstract the signing configuration to a separate file to avoid hardcoding this. // TODO: Abstract the signing configuration to a separate file to avoid hardcoding this.

@ -39,7 +39,7 @@ android {
} }
buildTypes { buildTypes {
val debug by getting { debug {
applicationIdSuffix = NiaBuildType.DEBUG.applicationIdSuffix applicationIdSuffix = NiaBuildType.DEBUG.applicationIdSuffix
} }
val release by getting { val release by getting {
@ -52,7 +52,7 @@ android {
// TODO: Abstract the signing configuration to a separate file to avoid hardcoding this. // TODO: Abstract the signing configuration to a separate file to avoid hardcoding this.
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")
} }
val benchmark by creating { create("benchmark") {
// Enable all the optimizations from release build through initWith(release). // Enable all the optimizations from release build through initWith(release).
initWith(release) initWith(release)
matchingFallbacks.add("release") matchingFallbacks.add("release")
@ -65,7 +65,7 @@ android {
} }
} }
packagingOptions { packaging {
resources { resources {
excludes.add("/META-INF/{AL2.0,LGPL2.1}") excludes.add("/META-INF/{AL2.0,LGPL2.1}")
} }

@ -39,7 +39,7 @@ android {
// This benchmark buildType is used for benchmarking, and should function like your // This benchmark buildType is used for benchmarking, and should function like your
// release build (for example, with minification on). It's signed with a debug key // release build (for example, with minification on). It's signed with a debug key
// for easy local/CI testing. // for easy local/CI testing.
val benchmark by creating { create("benchmark") {
// Keep the build type debuggable so we can attach a debugger if needed. // Keep the build type debuggable so we can attach a debugger if needed.
isDebuggable = true isDebuggable = true
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")

@ -20,6 +20,7 @@ import com.google.samples.apps.nowinandroid.configureFlavors
import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureGradleManagedDevices
import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import com.google.samples.apps.nowinandroid.configurePrintApksTask import com.google.samples.apps.nowinandroid.configurePrintApksTask
import com.google.samples.apps.nowinandroid.disableUnnecessaryAndroidTests
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.api.artifacts.VersionCatalogsExtension
@ -44,6 +45,7 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
} }
extensions.configure<LibraryAndroidComponentsExtension> { extensions.configure<LibraryAndroidComponentsExtension> {
configurePrintApksTask(this) configurePrintApksTask(this)
disableUnnecessaryAndroidTests(target)
} }
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs") val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
configurations.configureEach { configurations.configureEach {

@ -0,0 +1,35 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import org.gradle.api.Project
/**
* Disable unnecessary Android instrumented tests for the [project] if there is no `androidTest` folder.
* Otherwise, these projects would be compiled, packaged, installed and ran only to end-up with the following message:
*
* > Starting 0 tests on AVD
*
* Note: this could be improved by checking other potential sourceSets based on buildTypes and flavors.
*/
internal fun LibraryAndroidComponentsExtension.disableUnnecessaryAndroidTests(
project: Project,
) = beforeVariants {
it.enableAndroidTest = it.enableAndroidTest
&& project.projectDir.resolve("src/androidTest").exists()
}

@ -20,7 +20,6 @@ import com.android.build.api.dsl.CommonExtension
import com.android.build.api.dsl.ManagedVirtualDevice import com.android.build.api.dsl.ManagedVirtualDevice
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.kotlin.dsl.invoke import org.gradle.kotlin.dsl.invoke
import java.util.Locale
/** /**
* Configure project for Gradle managed devices * Configure project for Gradle managed devices
@ -55,7 +54,7 @@ private data class DeviceConfig(
val systemImageSource: String, val systemImageSource: String,
) { ) {
val taskName = buildString { val taskName = buildString {
append(device.toLowerCase(Locale.ROOT).replace(" ", "")) append(device.lowercase().replace(" ", ""))
append("api") append("api")
append(apiLevel.toString()) append(apiLevel.toString())
append(systemImageSource.replace("-", "")) append(systemImageSource.replace("-", ""))

@ -27,6 +27,7 @@ import org.gradle.kotlin.dsl.withType
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
import org.gradle.testing.jacoco.tasks.JacocoReport import org.gradle.testing.jacoco.tasks.JacocoReport
import java.util.Locale
private val coverageExclusions = listOf( private val coverageExclusions = listOf(
// Android // Android
@ -36,6 +37,10 @@ private val coverageExclusions = listOf(
"**/Manifest*.*" "**/Manifest*.*"
) )
private fun String.capitalize() = replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}
internal fun Project.configureJacoco( internal fun Project.configureJacoco(
androidComponentsExtension: AndroidComponentsExtension<*, *, *>, androidComponentsExtension: AndroidComponentsExtension<*, *, *>,
) { ) {

@ -62,7 +62,6 @@ internal fun Project.configureKotlinAndroid(
// Enable experimental coroutines APIs, including Flow // Enable experimental coroutines APIs, including Flow
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-opt-in=kotlinx.coroutines.FlowPreview", "-opt-in=kotlinx.coroutines.FlowPreview",
"-opt-in=kotlin.Experimental",
) )
} }
} }

@ -53,10 +53,6 @@ class TestTopicDao : TopicDao {
return topicEntities.map { it.id.toLong() } return topicEntities.map { it.id.toLong() }
} }
override suspend fun updateTopics(entities: List<TopicEntity>) {
throw NotImplementedError("Unused in tests")
}
override suspend fun upsertTopics(entities: List<TopicEntity>) { override suspend fun upsertTopics(entities: List<TopicEntity>) {
// Overwrite old values with new values // Overwrite old values with new values
entitiesStateFlow.update { oldValues -> entitiesStateFlow.update { oldValues ->

@ -14,8 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
@Suppress("DSL_SCOPE_VIOLATION")
plugins { plugins {
id("nowinandroid.android.library") id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco") id("nowinandroid.android.library.jacoco")

@ -20,7 +20,6 @@ import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Update
import androidx.room.Upsert import androidx.room.Upsert
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -58,12 +57,6 @@ interface TopicDao {
@Insert(onConflict = OnConflictStrategy.IGNORE) @Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertOrIgnoreTopics(topicEntities: List<TopicEntity>): List<Long> suspend fun insertOrIgnoreTopics(topicEntities: List<TopicEntity>): List<Long>
/**
* Updates [entities] in the db that match the primary key, and no-ops if they don't
*/
@Update
suspend fun updateTopics(entities: List<TopicEntity>)
/** /**
* Inserts or updates [entities] in the db under the specified primary keys * Inserts or updates [entities] in the db under the specified primary keys
*/ */

@ -14,8 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
@Suppress("DSL_SCOPE_VIOLATION")
plugins { plugins {
id("nowinandroid.android.library") id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco") id("nowinandroid.android.library.jacoco")
@ -43,10 +41,10 @@ protobuf {
generateProtoTasks { generateProtoTasks {
all().forEach { task -> all().forEach { task ->
task.builtins { task.builtins {
val java by registering { register("java") {
option("lite") option("lite")
} }
val kotlin by registering { register("kotlin") {
option("lite") option("lite")
} }
} }

@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
@Suppress("DSL_SCOPE_VIOLATION")
plugins { plugins {
id("kotlin") id("kotlin")
} }

@ -64,7 +64,7 @@ Here's what's happening in each step. The easiest way to find the associated cod
</td> </td>
<td>On app startup, a <a href="https://developer.android.com/topic/libraries/architecture/workmanager">WorkManager</a> job to sync all repositories is enqueued. <td>On app startup, a <a href="https://developer.android.com/topic/libraries/architecture/workmanager">WorkManager</a> job to sync all repositories is enqueued.
</td> </td>
<td><code>SyncInitializer.create</code> <td><code>Sync.initialize</code>
</td> </td>
</tr> </tr>
<tr> <tr>

@ -6,7 +6,7 @@ androidxActivity = "1.7.0"
androidxAppCompat = "1.5.1" androidxAppCompat = "1.5.1"
androidxBrowser = "1.4.0" androidxBrowser = "1.4.0"
androidxComposeBom = "2023.01.00" androidxComposeBom = "2023.01.00"
androidxComposeCompiler = "1.4.4" androidxComposeCompiler = "1.4.5"
androidxComposeMaterial3 = "1.1.0-alpha06" androidxComposeMaterial3 = "1.1.0-alpha06"
androidxComposeRuntimeTracing = "1.0.0-alpha01" androidxComposeRuntimeTracing = "1.0.0-alpha01"
androidxCore = "1.9.0" androidxCore = "1.9.0"
@ -37,11 +37,11 @@ hilt = "2.44.2"
hiltExt = "1.0.0" hiltExt = "1.0.0"
jacoco = "0.8.7" jacoco = "0.8.7"
junit4 = "4.13.2" junit4 = "4.13.2"
kotlin = "1.8.10" kotlin = "1.8.20"
kotlinxCoroutines = "1.6.4" kotlinxCoroutines = "1.6.4"
kotlinxDatetime = "0.4.0" kotlinxDatetime = "0.4.0"
kotlinxSerializationJson = "1.5.0" kotlinxSerializationJson = "1.5.0"
ksp = "1.8.10-1.0.9" ksp = "1.8.20-1.0.11"
lint = "30.3.1" lint = "30.3.1"
okhttp = "4.10.0" okhttp = "4.10.0"
protobuf = "3.21.12" protobuf = "3.21.12"

@ -19,10 +19,11 @@ package com.google.samples.apps.nowinandroid.sync.services
import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage import com.google.firebase.messaging.RemoteMessage
import com.google.samples.apps.nowinandroid.core.data.util.SyncManager import com.google.samples.apps.nowinandroid.core.data.util.SyncManager
import com.google.samples.apps.nowinandroid.sync.initializers.SYNC_TOPIC
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
private const val SYNC_TOPIC_SENDER = "/topics/sync"
@AndroidEntryPoint @AndroidEntryPoint
class SyncNotificationsService : FirebaseMessagingService() { class SyncNotificationsService : FirebaseMessagingService() {
@ -30,7 +31,7 @@ class SyncNotificationsService : FirebaseMessagingService() {
lateinit var syncManager: SyncManager lateinit var syncManager: SyncManager
override fun onMessageReceived(message: RemoteMessage) { override fun onMessageReceived(message: RemoteMessage) {
if (SYNC_TOPIC == message.from) { if (SYNC_TOPIC_SENDER == message.from) {
syncManager.requestSync() syncManager.requestSync()
} }
} }

Loading…
Cancel
Save