Skip to content
This repository was archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
Improve Application signing validation (#19)
Browse files Browse the repository at this point in the history
* Improve Application signing validation

* fix: configuration cache wasn't happy

* if a config doesn't have a signingConfig threat it as default
  • Loading branch information
CristianGM authored May 10, 2022
1 parent 0a5bcd5 commit 4b682be
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 20 deletions.
23 changes: 14 additions & 9 deletions src/main/kotlin/io/github/flank/gradle/simple-flank.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,24 @@ plugins.withType<AppPlugin> {
val appApk: Apk = Apk.from(debugApkDir, builtArtifactsLoader)
val testApk: Apk = Apk.from(testApkDir, builtArtifactsLoader)

variant.androidTest?.instrumentationRunner
configureTasks(
variant,
variant.androidTest!!,
appApk,
testApk,
requireNotNull(project.extensions.findByType<ApplicationExtension>()))
val applicationExtension =
requireNotNull(project.extensions.findByType<ApplicationExtension>())
configureTasks(variant, variant.androidTest!!, appApk, testApk, applicationExtension)

val signingConfigName =
applicationExtension.buildTypes.getByName(variant.buildType!!).signingConfig?.name
val signingConfig =
signingConfigName?.let { applicationExtension.signingConfigs.named(it).get() }
tasks.named<FlankRunTask>("flankRun${variant.name.capitalize()}").configure {
doFirst {
verifyNotDefaultKeystore(
this@configure.variant.get(), hermeticTests.getOrElse(false), logger, signingConfig)
}
}
}
}
tasks.register<FlankVersionTask>("flankVersion") { flankJarClasspath.from(flankExecutable) }
registerRunFlankTask()
verifyNotDefaultKeystore()
}

plugins.withType<LibraryPlugin> {
Expand All @@ -56,7 +62,6 @@ plugins.withType<LibraryPlugin> {
val appApk: Apk = Apk.from(copySmallAppTask.appApk)
val testApk: Apk = Apk.from(testApkDir, builtArtifactsLoader)

variant.androidTest?.instrumentationRunner
configureTasks(
variant,
variant.androidTest!!,
Expand Down
28 changes: 17 additions & 11 deletions src/main/kotlin/io/github/flank/gradle/utils/keystoreUtils.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
package io.github.flank.gradle.utils

import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.SigningConfig
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.internal.tasks.ValidateSigningTask
import io.github.flank.gradle.SimpleFlankExtension
import java.io.File
import org.gradle.api.Project
import org.gradle.api.logging.Logger
import org.gradle.api.tasks.Copy
import org.gradle.kotlin.dsl.maybeCreate
import org.gradle.kotlin.dsl.withType

fun Project.verifyNotDefaultKeystore() {
val androidExtension = project.extensions.getByName("android") as ApplicationExtension
afterEvaluate {
androidExtension.signingConfigs {
named("debug") {
if (storeFile?.path?.contains("/.android/debug.keystore") == true) {
println(
"Warning: The debug keystore should be set, using the default means the cache won't work")
}
}
fun verifyNotDefaultKeystore(
variantName: String,
hermeticTest: Boolean,
logger: Logger,
signingConfig: SigningConfig?
) {
val signingConfigFile = signingConfig?.storeFile

if (signingConfigFile?.path?.contains("/.android/debug.keystore") != false) {
val message =
"The $variantName keystore should be set, using the default means the cache won't work"
if (hermeticTest) {
throw RuntimeException(message, null)
} else {
logger.warn("Warning: $message")
}
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/test/kotlin/PerformanceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ class PerformanceTest : GradleTest() {
File(testProjectDir.root, "build.gradle.kts")
.appendText(
"""
android {
signingConfigs {
create("mySigning") {
storeFile = File(projectDir, "someKeystore")
keyAlias = "debugKey"
keyPassword = "debugKeystore"
storePassword = "debugKeystore"
}
}
buildTypes {
getByName("debug") {
signingConfig = signingConfigs.getByName("mySigning")
}
}
}
simpleFlank {
hermeticTests.set(true)
}
Expand All @@ -88,6 +103,26 @@ class PerformanceTest : GradleTest() {
@Test
fun appFlankRunWithPropertyIsCacheable() {
projectFromResources("app")
File(testProjectDir.root, "build.gradle.kts")
.appendText(
"""
android {
signingConfigs {
create("mySigning") {
storeFile = File(projectDir, "someKeystore")
keyAlias = "debugKey"
keyPassword = "debugKeystore"
storePassword = "debugKeystore"
}
}
buildTypes {
getByName("debug") {
signingConfig = signingConfigs.getByName("mySigning")
}
}
}
""".trimIndent())

File(testProjectDir.root, "gradle.properties").appendText("simple-flank.hermeticTests=true\n")

gradleRunner("flankRun", "--stacktrace").forwardOutput().build()
Expand Down
110 changes: 110 additions & 0 deletions src/test/kotlin/SigningValidationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import java.io.File
import org.junit.Test
import strikt.api.expectThat
import strikt.assertions.contains

class SigningValidationTest : GradleTest() {
@Test
fun warnIfDefaultSigning() {
projectFromResources("app")

val build = gradleRunner("flankRunDebug").forwardOutput().build()

expectThat(build.output) { contains("Warning: The debug keystore should be set") }
}

@Test
fun failIfDefaultSigningAndHermeticTests() {
projectFromResources("app")
File(testProjectDir.root, "build.gradle.kts")
.appendText(
"""
simpleFlank {
hermeticTests.set(true)
}
""".trimIndent())

gradleRunner("flankRunDebug").forwardOutput().buildAndFail()
}

@Test
fun failIfNoSigningAndHermeticTests() {
projectFromResources("app")
File(testProjectDir.root, "build.gradle.kts")
.appendText(
"""
android {
testBuildType = "beta"
buildTypes {
create("beta")
}
}
simpleFlank {
hermeticTests.set(true)
}
""".trimIndent())

gradleRunner("flankRunDebug").forwardOutput().buildAndFail()
}

@Test
fun workFineIfCustomSigning() {
projectFromResources("app")
File(testProjectDir.root, "build.gradle.kts")
.appendText(
"""
android {
signingConfigs {
named("debug") {
storeFile = File(projectDir, "someKeystore")
keyAlias = "debugKey"
keyPassword = "debugKeystore"
storePassword = "debugKeystore"
}
}
buildTypes {
getByName("debug") {
signingConfig = signingConfigs.getByName("debug")
}
}
}
simpleFlank {
hermeticTests.set(true)
}
""".trimIndent())

val build = gradleRunner("flankRunDebug").forwardOutput().build()

expectThat(build.output) { not { contains("The debug keystore should be set") } }
}

@Test
fun workFineNotOnlyWithDebugSigningConfig() {
projectFromResources("app")
File(testProjectDir.root, "build.gradle.kts")
.appendText(
"""
android {
signingConfigs {
create("mySigning") {
storeFile = File(projectDir, "someKeystore")
keyAlias = "debugKey"
keyPassword = "debugKeystore"
storePassword = "debugKeystore"
}
}
buildTypes {
getByName("debug") {
signingConfig = signingConfigs.getByName("mySigning")
}
}
}
simpleFlank {
hermeticTests.set(true)
}
""".trimIndent())

gradleRunner("flankRunDebug").forwardOutput().build()
}
}
Binary file added src/test/resources/app/someKeystore
Binary file not shown.

0 comments on commit 4b682be

Please sign in to comment.