Merge pull request #305 from android/sep26-merge

Sep 26th gerrit -> github merge
pull/306/head
Don Turner 2 years ago committed by GitHub
commit 46deba844e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -6,7 +6,7 @@ label: 'triage me'
Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
- [ ] Make sure to open a GitHub issue as a bug/feature request before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea
- [ ] Ensure the tests and linter pass (`./gradlew spotlessApply` to automatically apply formatting)
- [ ] Ensure the tests and linter pass (`./gradlew --init-script gradle/init.gradle.kts spotlessApply` to automatically apply formatting)
- [ ] Appropriate docs were updated (if necessary)
Is this your first Pull Request?

@ -34,10 +34,10 @@ jobs:
uses: gradle/gradle-build-action@v2
- name: Check spotless
run: ./gradlew spotlessCheck --stacktrace
run: ./gradlew spotlessCheck --init-script gradle/init.gradle.kts --no-configuration-cache --stacktrace
- name: Check lint
run: ./gradlew lintDebug --stacktrace
run: ./gradlew lintDemoDebug --stacktrace
- name: Build all build type and flavor permutations
run: ./gradlew assemble --stacktrace

@ -16,7 +16,6 @@
plugins {
id("nowinandroid.android.application")
id("nowinandroid.android.application.compose")
id("nowinandroid.spotless")
}
android {

@ -20,10 +20,8 @@ plugins {
id("nowinandroid.android.application")
id("nowinandroid.android.application.compose")
id("nowinandroid.android.application.jacoco")
kotlin("kapt")
id("nowinandroid.android.hilt")
id("jacoco")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
id("nowinandroid.firebase-perf")
}
@ -67,19 +65,6 @@ android {
}
}
// @see Flavor for more details on the app product flavors.
flavorDimensions += FlavorDimension.contentType.name
productFlavors {
Flavor.values().forEach {
create(it.name) {
dimension = it.dimension.name
if (it.applicationIdSuffix != null) {
applicationIdSuffix = it.applicationIdSuffix
}
}
}
}
packagingOptions {
resources {
excludes.add("/META-INF/{AL2.0,LGPL2.1}")
@ -124,17 +109,13 @@ dependencies {
implementation(libs.coil.kt)
implementation(libs.coil.kt.svg)
}
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
kaptAndroidTest(libs.hilt.compiler)
// androidx.test is forcing JUnit, 4.12. This forces it to use 4.13
configurations.configureEach {
resolutionStrategy {
force(libs.junit4)
// Temporary workaround for https://issuetracker.google.com/174733673
force("org.objenesis:objenesis:2.6")
}
// androidx.test is forcing JUnit, 4.12. This forces it to use 4.13
configurations.configureEach {
resolutionStrategy {
force(libs.junit4)
// Temporary workaround for https://issuetracker.google.com/174733673
force("org.objenesis:objenesis:2.6")
}
}

@ -25,7 +25,8 @@ import androidx.compose.ui.test.performClick
import androidx.test.espresso.Espresso
import androidx.test.espresso.NoActivityResumedException
import com.google.samples.apps.nowinandroid.MainActivity
import com.google.samples.apps.nowinandroid.R
import com.google.samples.apps.nowinandroid.feature.foryou.R as FeatureForyouR
import com.google.samples.apps.nowinandroid.feature.interests.R as FeatureInterestsR
import dagger.hilt.android.testing.BindValue
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
@ -70,11 +71,11 @@ class NavigationTest {
@Before
fun setup() {
composeTestRule.activity.apply {
done = getString(R.string.done)
navigateUp = getString(R.string.navigate_up)
forYouLoading = getString(R.string.for_you_loading)
forYou = getString(R.string.for_you)
interests = getString(R.string.interests)
done = getString(FeatureForyouR.string.done)
navigateUp = getString(FeatureForyouR.string.navigate_up)
forYouLoading = getString(FeatureForyouR.string.for_you_loading)
forYou = getString(FeatureForyouR.string.for_you)
interests = getString(FeatureInterestsR.string.interests)
sampleTopic = "Headlines"
}
}

@ -19,7 +19,6 @@ import com.google.samples.apps.nowinandroid.configureFlavors
plugins {
id("nowinandroid.android.test")
id("nowinandroid.spotless")
}
android {
@ -30,6 +29,10 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
buildConfig = true
}
buildTypes {
// 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

@ -29,8 +29,6 @@ setup.
Current list of convention plugins:
- [`nowinandroid.spotless`](convention/src/main/kotlin/SpotlessConventionPlugin.kt):
Configures spotless.
- [`nowinandroid.android.application`](convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt),
[`nowinandroid.android.library`](convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt),
[`nowinandroid.android.test`](convention/src/main/kotlin/AndroidTestConventionPlugin.kt):

@ -28,7 +28,6 @@ java {
dependencies {
compileOnly(libs.android.gradlePlugin)
compileOnly(libs.kotlin.gradlePlugin)
compileOnly(libs.spotless.gradlePlugin)
}
gradlePlugin {
@ -65,9 +64,9 @@ gradlePlugin {
id = "nowinandroid.android.test"
implementationClass = "AndroidTestConventionPlugin"
}
register("spotless") {
id = "nowinandroid.spotless"
implementationClass = "SpotlessConventionPlugin"
register("androidHilt") {
id = "nowinandroid.android.hilt"
implementationClass = "AndroidHiltConventionPlugin"
}
register("firebase-perf") {
id = "nowinandroid.firebase-perf"

@ -14,7 +14,7 @@
* limitations under the License.
*/
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
import com.android.build.api.dsl.ApplicationExtension
import com.google.samples.apps.nowinandroid.configureAndroidCompose
import org.gradle.api.Plugin
import org.gradle.api.Project
@ -24,7 +24,7 @@ class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.android.application")
val extension = extensions.getByType<BaseAppModuleExtension>()
val extension = extensions.getByType<ApplicationExtension>()
configureAndroidCompose(extension)
}
}

@ -14,8 +14,11 @@
* limitations under the License.
*/
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.api.dsl.ApplicationExtension
import com.google.samples.apps.nowinandroid.configureFlavors
import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import com.google.samples.apps.nowinandroid.configurePrintApksTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
@ -28,9 +31,13 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
apply("org.jetbrains.kotlin.android")
}
extensions.configure<BaseAppModuleExtension> {
extensions.configure<ApplicationExtension> {
configureKotlinAndroid(this)
defaultConfig.targetSdk = 33
configureFlavors(this)
}
extensions.configure<ApplicationAndroidComponentsExtension> {
configurePrintApksTask(this)
}
}
}

@ -26,9 +26,8 @@ class AndroidFeatureConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply {
apply("com.android.library")
apply("org.jetbrains.kotlin.android")
apply("org.jetbrains.kotlin.kapt")
apply("nowinandroid.android.library")
apply("nowinandroid.android.hilt")
}
extensions.configure<LibraryExtension> {
defaultConfig {
@ -59,9 +58,6 @@ class AndroidFeatureConventionPlugin : Plugin<Project> {
add("implementation", libs.findLibrary("kotlinx.coroutines.android").get())
add("implementation", libs.findLibrary("hilt.android").get())
add("kapt", libs.findLibrary("hilt.compiler").get())
// TODO : Remove this dependency once we upgrade to Android Studio Dolphin b/228889042
// These dependencies are currently necessary to render Compose previews
add(

@ -0,0 +1,44 @@
/*
* Copyright 2022 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.
*/
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.google.samples.apps.nowinandroid.configureJacoco
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.kotlin
class AndroidHiltConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("org.jetbrains.kotlin.kapt")
apply("dagger.hilt.android.plugin")
}
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
"implementation"(libs.findLibrary("hilt.android").get())
"kapt"(libs.findLibrary("hilt.compiler").get())
"kaptAndroidTest"(libs.findLibrary("hilt.compiler").get())
}
}
}
}

@ -14,9 +14,12 @@
* limitations under the License.
*/
import com.android.build.api.variant.AndroidComponentsExtension
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.gradle.LibraryExtension
import com.google.samples.apps.nowinandroid.configureFlavors
import com.google.samples.apps.nowinandroid.configureKotlinAndroid
import com.google.samples.apps.nowinandroid.configurePrintApksTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
@ -37,18 +40,17 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
defaultConfig.targetSdk = 33
configureFlavors(this)
}
extensions.configure<LibraryAndroidComponentsExtension> {
configurePrintApksTask(this)
}
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
configurations.configureEach {
resolutionStrategy {
force(libs.findLibrary("junit4").get())
// Temporary workaround for https://issuetracker.google.com/174733673
force("org.objenesis:objenesis:2.6")
}
configurations.configureEach {
resolutionStrategy {
force(libs.findLibrary("junit4").get())
// Temporary workaround for https://issuetracker.google.com/174733673
force("org.objenesis:objenesis:2.6")
}
}
}
}
}

@ -1,53 +0,0 @@
/*
* Copyright 2022 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.
*/
import com.diffplug.gradle.spotless.SpotlessExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.getByType
class SpotlessConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.diffplug.spotless")
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
extensions.configure<SpotlessExtension> {
kotlin {
target("**/*.kt")
targetExclude("**/build/**/*.kt")
ktlint(libs.findVersion("ktlint").get().toString()).userData(mapOf("android" to "true"))
licenseHeaderFile(rootProject.file("spotless/copyright.kt"))
}
format("kts") {
target("**/*.kts")
targetExclude("**/build/**/*.kts")
// Look for the first line that doesn't have a block comment (assumed to be the license)
licenseHeaderFile(rootProject.file("spotless/copyright.kts"), "(^(?![\\/ ]\\*).*$)")
}
format("xml") {
target("**/*.xml")
targetExclude("**/build/**/*.xml")
// Look for the first XML tag that isn't a comment (<!--) or the xml declaration (<?xml)
licenseHeaderFile(rootProject.file("spotless/copyright.xml"), "(<[^!?])")
}
}
}
}
}

@ -1,5 +1,8 @@
package com.google.samples.apps.nowinandroid
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.ApplicationProductFlavor
import com.android.build.api.dsl.ApplicationVariantDimension
import com.android.build.api.dsl.CommonExtension
import org.gradle.api.Project
@ -24,6 +27,11 @@ fun Project.configureFlavors(
Flavor.values().forEach{
create(it.name) {
dimension = it.dimension.name
if (this@apply is ApplicationExtension && this is ApplicationProductFlavor) {
if (it.applicationIdSuffix != null) {
this.applicationIdSuffix = it.applicationIdSuffix
}
}
}
}
}

@ -0,0 +1,98 @@
/*
* Copyright 2022 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.artifact.SingleArtifact
import com.android.build.api.variant.AndroidComponentsExtension
import com.android.build.api.variant.BuiltArtifactsLoader
import com.android.build.api.variant.HasAndroidTest
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import java.io.File
internal fun Project.configurePrintApksTask(extension: AndroidComponentsExtension<*, *, *>) {
extension.onVariants { variant ->
if (variant is HasAndroidTest) {
val loader = variant.artifacts.getBuiltArtifactsLoader()
val artifact = variant.androidTest?.artifacts?.get(SingleArtifact.APK)
val javaSources = variant.androidTest?.sources?.java?.all
val kotlinSources = variant.androidTest?.sources?.kotlin?.all
val testSources = if (javaSources != null && kotlinSources != null) {
javaSources.zip(kotlinSources) { javaDirs, kotlinDirs ->
javaDirs + kotlinDirs
}
} else javaSources ?: kotlinSources
if (artifact != null && testSources != null) {
tasks.register(
"${variant.name}PrintTestApk",
PrintApkLocationTask::class.java
) {
apkFolder.set(artifact)
builtArtifactsLoader.set(loader)
variantName.set(variant.name)
sources.set(testSources)
}
}
}
}
}
internal abstract class PrintApkLocationTask : DefaultTask() {
@get:InputDirectory
abstract val apkFolder: DirectoryProperty
@get:InputFiles
abstract val sources: ListProperty<Directory>
@get:Internal
abstract val builtArtifactsLoader: Property<BuiltArtifactsLoader>
@get:Input
abstract val variantName: Property<String>
@TaskAction
fun taskAction() {
val hasFiles = sources.orNull?.any { directory ->
directory.asFileTree.files.any {
it.isFile && it.parentFile.path.contains("build${File.separator}generated").not()
}
} ?: throw RuntimeException("Cannot check androidTest sources")
// Don't print APK location if there are no androidTest source files
if (!hasFiles) {
return
}
val builtArtifacts = builtArtifactsLoader.get().load(apkFolder.get())
?: throw RuntimeException("Cannot load APKs")
if (builtArtifacts.elements.size != 1)
throw RuntimeException("Expected one APK !")
val apk = File(builtArtifacts.elements.single().outputFile).toPath()
println(apk)
}
}

@ -28,4 +28,5 @@ dependencyResolutionManagement {
}
}
rootProject.name = "build-logic"
include(":convention")

@ -31,5 +31,4 @@ plugins {
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.hilt) apply false
alias(libs.plugins.secrets) apply false
alias(libs.plugins.spotless) apply false
}

@ -16,14 +16,10 @@
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco")
kotlin("kapt")
id("nowinandroid.spotless")
id("nowinandroid.android.hilt")
}
dependencies {
implementation(libs.kotlinx.coroutines.android)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
testImplementation(project(":core:testing"))
}

@ -15,16 +15,10 @@
*/
plugins {
id("nowinandroid.android.library")
kotlin("kapt")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
id("nowinandroid.android.hilt")
}
dependencies {
api(project(":core:data"))
implementation(project(":core:testing"))
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
kaptAndroidTest(libs.hilt.compiler)
}

@ -16,10 +16,8 @@
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco")
kotlin("kapt")
id("nowinandroid.android.hilt")
id("kotlinx-serialization")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
}
dependencies {
@ -35,7 +33,4 @@ dependencies {
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.serialization.json)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
}

@ -18,10 +18,8 @@
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco")
kotlin("kapt")
id("dagger.hilt.android.plugin")
id("nowinandroid.android.hilt")
alias(libs.plugins.ksp)
id("nowinandroid.spotless")
}
android {
@ -47,8 +45,5 @@ dependencies {
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.datetime)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
androidTestImplementation(project(":core:testing"))
}

@ -15,9 +15,7 @@
*/
plugins {
id("nowinandroid.android.library")
kotlin("kapt")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
id("nowinandroid.android.hilt")
}
dependencies {
@ -25,8 +23,4 @@ dependencies {
implementation(project(":core:testing"))
api(libs.androidx.dataStore.core)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
kaptAndroidTest(libs.hilt.compiler)
}

@ -24,10 +24,8 @@ import com.google.protobuf.gradle.protoc
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco")
kotlin("kapt")
id("dagger.hilt.android.plugin")
id("nowinandroid.android.hilt")
alias(libs.plugins.protobuf)
id("nowinandroid.spotless")
}
android {
@ -65,10 +63,6 @@ dependencies {
implementation(libs.androidx.dataStore.core)
implementation(libs.protobuf.kotlin.lite)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
kaptAndroidTest(libs.hilt.compiler)
}
// TODO b/239411851, Remove kapt workaround configuration

@ -17,7 +17,6 @@ plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
id("nowinandroid.spotless")
}
android {

@ -17,7 +17,6 @@
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
id("kotlin")
id("nowinandroid.spotless")
}
dependencies {

@ -18,16 +18,10 @@
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco")
kotlin("kapt")
id("dagger.hilt.android.plugin")
alias(libs.plugins.ksp)
id("nowinandroid.spotless")
id("nowinandroid.android.hilt")
}
dependencies {
api(libs.androidx.hilt.navigation.compose)
api(libs.androidx.navigation.compose)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
}

@ -13,16 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco")
kotlin("kapt")
id("nowinandroid.android.hilt")
id("kotlinx-serialization")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
}
android {
buildFeatures {
buildConfig = true
}
}
secrets {
defaultPropertiesFileName = "secrets.defaults.properties"
}
@ -40,7 +45,4 @@ dependencies {
implementation(libs.okhttp.logging)
implementation(libs.retrofit.core)
implementation(libs.retrofit.kotlin.serialization)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
}

@ -15,8 +15,7 @@
*/
plugins {
id("nowinandroid.android.library")
kotlin("kapt")
id("nowinandroid.spotless")
id("nowinandroid.android.hilt")
}
dependencies {
@ -24,9 +23,6 @@ dependencies {
implementation(project(":core:data"))
implementation(project(":core:model"))
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
api(libs.junit4)
api(libs.androidx.test.core)
api(libs.kotlinx.coroutines.test)

@ -17,7 +17,6 @@ plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
id("nowinandroid.spotless")
}
dependencies {

@ -57,6 +57,7 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import com.google.samples.apps.nowinandroid.core.designsystem.R as DesignsystemR
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaToggleButton
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopicTag
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
@ -135,7 +136,7 @@ fun NewsResourceHeaderImage(
) {
AsyncImage(
placeholder = if (LocalInspectionMode.current) {
painterResource(R.drawable.ic_placeholder_default)
painterResource(DesignsystemR.drawable.ic_placeholder_default)
} else {
// TODO b/228077205, show specific loading image visual
null

@ -14,12 +14,9 @@
* limitations under the License.
*/
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.feature")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
}
dependencies {

@ -209,7 +209,9 @@ private fun AuthorToolbar(
IconButton(onClick = { onBackClick() }) {
Icon(
imageVector = Filled.ArrowBack,
contentDescription = stringResource(id = R.string.back)
contentDescription = stringResource(
id = com.google.samples.apps.nowinandroid.core.ui.R.string.back
)
)
}
val selected = uiState.isFollowed

@ -14,12 +14,9 @@
* limitations under the License.
*/
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.feature")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
}
dependencies {

@ -14,12 +14,9 @@
* limitations under the License.
*/
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.feature")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
}
dependencies {

@ -14,10 +14,7 @@
* limitations under the License.
*/
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.feature")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
}

@ -14,12 +14,9 @@
* limitations under the License.
*/
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.feature")
id("nowinandroid.android.library.compose")
id("nowinandroid.android.library.jacoco")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
}
dependencies {

@ -211,7 +211,9 @@ private fun TopicToolbar(
IconButton(onClick = { onBackClick() }) {
Icon(
imageVector = Filled.ArrowBack,
contentDescription = stringResource(id = R.string.back)
contentDescription = stringResource(
id = com.google.samples.apps.nowinandroid.core.ui.R.string.back
)
)
}
val selected = uiState.isFollowed

@ -4,17 +4,26 @@
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.configureondemand=true
org.gradle.caching=true
org.gradle.parallel=true
# Ensure important default jvmargs aren't overwritten. See https://github.com/gradle/gradle/issues/19750
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
org.gradle.parallel=true
# Not encouraged by Gradle and can produce weird results. Wait for isolated projects instead.
org.gradle.configureondemand=false
# Enable caching between builds.
org.gradle.caching=true
# Enable configuration caching between builds.
org.gradle.unsafe.configuration-cache=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
@ -23,3 +32,14 @@ android.useAndroidX=true
kotlin.code.style=official
# Allow kapt to use incremental processing
kapt.incremental.apt=true
# Non-transitive R classes is recommended and is faster/smaller
android.nonTransitiveRClass=true
# Disable build features that are enabled by default,
# https://developer.android.com/studio/releases/gradle-plugin#buildFeatures
android.defaults.buildfeatures.buildconfig=false
android.defaults.buildfeatures.aidl=false
android.defaults.buildfeatures.renderscript=false
android.defaults.buildfeatures.resvalues=false
android.defaults.buildfeatures.shaders=false

@ -0,0 +1,56 @@
/*
* Copyright 2022 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.
*/
val ktlintVersion = "0.43.0"
initscript {
val spotlessVersion = "6.7.2"
repositories {
mavenCentral()
}
dependencies {
classpath("com.diffplug.spotless:spotless-plugin-gradle:$spotlessVersion")
}
}
allprojects {
if (this == rootProject) {
return@allprojects
}
apply<com.diffplug.gradle.spotless.SpotlessPlugin>()
extensions.configure<com.diffplug.gradle.spotless.SpotlessExtension> {
kotlin {
target("**/*.kt")
targetExclude("**/build/**/*.kt")
ktlint(ktlintVersion).userData(mapOf("android" to "true"))
licenseHeaderFile(rootProject.file("spotless/copyright.kt"))
}
format("kts") {
target("**/*.kts")
targetExclude("**/build/**/*.kts")
// Look for the first line that doesn't have a block comment (assumed to be the license)
licenseHeaderFile(rootProject.file("spotless/copyright.kts"), "(^(?![\\/ ]\\*).*$)")
}
format("xml") {
target("**/*.xml")
targetExclude("**/build/**/*.xml")
// Look for the first XML tag that isn't a comment (<!--) or the xml declaration (<?xml)
licenseHeaderFile(rootProject.file("spotless/copyright.xml"), "(<[^!?])")
}
}
}

@ -39,7 +39,6 @@ kotlinxCoroutines = "1.6.4"
kotlinxDatetime = "0.4.0"
kotlinxSerializationJson = "1.4.0"
ksp = "1.7.10-1.0.6"
ktlint = "0.43.0"
lint = "30.2.2"
okhttp = "4.10.0"
protobuf = "3.21.5"
@ -48,7 +47,6 @@ retrofit = "2.9.0"
retrofitKotlinxSerializationJson = "0.8.0"
room = "2.4.3"
secrets = "2.0.1"
spotless = "6.7.2"
turbine = "0.8.0"
[libraries]
@ -122,7 +120,6 @@ room-compiler = { group = "androidx.room", name = "room-compiler", version.ref =
# Dependencies of the included build-logic
android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" }
kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
spotless-gradlePlugin = { group = "com.diffplug.spotless", name = "spotless-plugin-gradle", version.ref = "spotless" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
@ -134,4 +131,3 @@ kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" }
secrets = { id = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin", version.ref = "secrets" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }

@ -58,12 +58,12 @@ run_firebase_test_lab() {
set +e # To not exit on an error to retry flaky tests
local counter=0
local result=1
local module=$1
local testApk=$1
while [ $result != 0 -a $counter -lt $MAX_RETRY ]; do
gcloud firebase test android run \
--type instrumentation \
--app "app/build/outputs/apk/demo/debug/app-demo-debug.apk" \
--test "$module/build/outputs/apk/androidTest/demo/debug/$module-demo-debug-androidTest.apk" \
--test "$testApk" \
--device-ids $deviceIds \
--os-version-ids $osVersionIds \
--locales en \
@ -76,17 +76,14 @@ run_firebase_test_lab() {
# All modules with androidTest to run tests on.
# This command will create a list like ["app", "sync"] based on which subdirectories
# (assumed to be modules) have an androidTest source directory.
# The sed regex pulls out the module name from the matched directory
modules=($(find . -regex ".*/src/androidTest" | sed -E 's|\./([^/]*)/.*|\1|g'))
testApks=($(./gradlew -q demoDebugPrintTestApk))
# Run all modules in parallel with Firebase Test Lab, and fail if any fail
pids=""
result=0
for module in ${modules[@]}; do
run_firebase_test_lab $module &
for testApk in ${testApks[@]}; do
run_firebase_test_lab $testApk &
pids="$pids $!"
done

@ -64,8 +64,8 @@ class DesignSystemDetector : Detector(), Detector.UastScanner {
id = "DesignSystem",
briefDescription = "Design system",
explanation = "This check highlights calls in code that use Compose Material " +
"composables instead of equivalents from the Now in Android design system " +
"module.",
"composables instead of equivalents from the Now in Android design system " +
"module.",
category = Category.CUSTOM_LINT_CHECKS,
priority = 7,
severity = Severity.ERROR,

@ -62,3 +62,17 @@ include(":feature:bookmarks")
include(":feature:topic")
include(":lint")
include(":sync")
val prePushHook = file(".git/hooks/pre-push")
val commitMsgHook = file(".git/hooks/commit-msg")
val hooksInstalled = commitMsgHook.exists()
&& prePushHook.exists()
&& prePushHook.readBytes().contentEquals(file("tools/pre-push").readBytes())
if (!hooksInstalled) {
exec {
commandLine("tools/setup.sh")
workingDir = rootProject.projectDir
}
}

@ -16,9 +16,7 @@
plugins {
id("nowinandroid.android.library")
id("nowinandroid.android.library.jacoco")
kotlin("kapt")
id("dagger.hilt.android.plugin")
id("nowinandroid.spotless")
id("nowinandroid.android.hilt")
}
android {
@ -43,12 +41,7 @@ dependencies {
testImplementation(project(":core:testing"))
androidTestImplementation(project(":core:testing"))
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
kapt(libs.hilt.ext.compiler)
androidTestImplementation(libs.androidx.work.testing)
kaptAndroidTest(libs.hilt.compiler)
kaptAndroidTest(libs.hilt.ext.compiler)
}

@ -69,7 +69,9 @@ private fun Context.syncWorkNotification(): Notification {
this,
SyncNotificationChannelID
)
.setSmallIcon(R.drawable.ic_nia_notification)
.setSmallIcon(
com.google.samples.apps.nowinandroid.core.common.R.drawable.ic_nia_notification
)
.setContentTitle(getString(R.string.sync_notification_title))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build()

@ -88,7 +88,7 @@ done
if [[ -n "$run_checks" ]]; then
# pre-push usually executes in the repository root, but just to be safe...
cd "$(git rev-parse --show-toplevel)"
./gradlew check
./gradlew --init-script gradle/init.gradle.kts --no-configuration-cache check
exit $?
fi

Loading…
Cancel
Save