summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2023-09-21 08:54:24 +0200
committerAlbin <albin@mullvad.net>2023-09-21 18:30:52 +0200
commit119da166330aaf5ef037f4269e36eedc5f142da9 (patch)
tree84a95ea7b89746c446bbbfaa232f2cd85d232d31
parent8066e42cff442207830ed05e6db1395e34c2d1db (diff)
downloadmullvadvpn-119da166330aaf5ef037f4269e36eedc5f142da9.tar.xz
mullvadvpn-119da166330aaf5ef037f4269e36eedc5f142da9.zip
Add billing and infrastructure flavor dimensions
Flavor dimension usage: * `billing` - used to build separate artifacts where (1) different policies are followed and (2) different dependencies are used. * `infrastructure` - used to improve development and testing against non-production environments.
-rw-r--r--android/app/build.gradle.kts96
-rw-r--r--android/buildSrc/src/main/kotlin/BuildVariants.kt44
-rw-r--r--android/service/build.gradle.kts7
-rw-r--r--android/test/common/build.gradle.kts4
-rw-r--r--android/test/e2e/build.gradle.kts4
-rw-r--r--android/test/mockapi/build.gradle.kts3
6 files changed, 143 insertions, 15 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 34313f689a..6c61206afe 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -2,6 +2,7 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.android.build.gradle.internal.tasks.factory.dependsOn
import java.io.FileInputStream
import java.util.*
+import org.gradle.configurationcache.extensions.capitalized
plugins {
id(Dependencies.Plugin.androidApplicationId)
@@ -47,19 +48,18 @@ android {
if (keystorePropertiesFile.exists()) {
signingConfigs {
- create("release") {
+ create(SigningConfigs.RELEASE) {
storeFile = file("$credentialsPath/app-keys.jks")
storePassword = keystoreProperties.getProperty("storePassword")
keyAlias = keystoreProperties.getProperty("keyAlias")
keyPassword = keystoreProperties.getProperty("keyPassword")
}
}
-
- buildTypes { getByName("release") { signingConfig = signingConfigs.getByName("release") } }
}
buildTypes {
- getByName("release") {
+ getByName(BuildTypes.RELEASE) {
+ signingConfig = signingConfigs.findByName(SigningConfigs.RELEASE)
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
@@ -67,18 +67,34 @@ android {
"proguard-rules.pro"
)
}
-
- create("fdroid") {
- initWith(buildTypes.getByName("release"))
- isMinifyEnabled = true
- isShrinkResources = true
+ create(BuildTypes.FDROID) {
+ initWith(buildTypes.getByName(BuildTypes.RELEASE))
signingConfig = null
- matchingFallbacks += "release"
+ matchingFallbacks += BuildTypes.RELEASE
}
+ create(BuildTypes.LEAK_CANARY) {
+ initWith(buildTypes.getByName(BuildTypes.DEBUG))
+ applicationIdSuffix = ".leakcanary"
+ matchingFallbacks += BuildTypes.DEBUG
+ }
+ }
+
+ flavorDimensions += FlavorDimensions.BILLING
+ flavorDimensions += FlavorDimensions.INFRASTRUCTURE
- create("leakCanary") {
- initWith(buildTypes.getByName("debug"))
- matchingFallbacks += "debug"
+ productFlavors {
+ create(Flavors.OSS) {
+ dimension = FlavorDimensions.BILLING
+ isDefault = true
+ }
+ create(Flavors.PLAY) { dimension = FlavorDimensions.BILLING }
+ create(Flavors.PROD) {
+ dimension = FlavorDimensions.INFRASTRUCTURE
+ isDefault = true
+ }
+ create(Flavors.DEVMOLE) {
+ dimension = FlavorDimensions.INFRASTRUCTURE
+ applicationId = "net.mullvad.mullvadvpn.devmole"
}
}
@@ -166,9 +182,63 @@ android {
)
}
+ applicationVariants.all {
+ val artifactSuffix = buildString {
+ productFlavors.getOrNull(0)?.name?.let { billingFlavorName ->
+ if (billingFlavorName != Flavors.OSS) {
+ append(".$billingFlavorName")
+ }
+ }
+
+ productFlavors.getOrNull(1)?.name?.let { infrastructureFlavorName ->
+ if (infrastructureFlavorName != Flavors.PROD) {
+ append(".$infrastructureFlavorName")
+ }
+ }
+
+ if (buildType.name != BuildTypes.RELEASE) {
+ append(".${buildType.name}")
+ }
+ }
+
+ val variantName = name
+ val capitalizedVariantName = variantName.capitalized()
+ val artifactName = "MullvadVPN-${versionName}${artifactSuffix}"
+
+ tasks.register<Copy>("create${capitalizedVariantName}DistApk") {
+ from(packageApplicationProvider)
+ into("${rootDir.parent}/dist")
+ include { it.name.endsWith(".apk") }
+ rename { "$artifactName.apk" }
+ }
+
+ val createDistBundle =
+ tasks.register<Copy>("create${capitalizedVariantName}DistBundle") {
+ from("$buildDir/outputs/bundle/$variantName")
+ into("${rootDir.parent}/dist")
+ include { it.name.endsWith(".aab") }
+ rename { "$artifactName.aab" }
+ }
+
+ createDistBundle.dependsOn("bundle$capitalizedVariantName")
+ }
+
project.tasks.preBuild.dependsOn("ensureJniDirectoryExist")
}
+androidComponents {
+ beforeVariants { variantBuilder ->
+ variantBuilder.enable =
+ variantBuilder.let { currentVariant ->
+ val enabledVariants =
+ enabledVariantTriples.map { (billing, infra, buildType) ->
+ billing + infra.capitalized() + buildType.capitalized()
+ }
+ enabledVariants.contains(currentVariant.name)
+ }
+ }
+}
+
configure<org.owasp.dependencycheck.gradle.extension.DependencyCheckExtension> {
// Skip the lintClassPath configuration, which relies on many dependencies that has been flagged
// to have CVEs, as it's related to the lint tooling rather than the project's compilation class
diff --git a/android/buildSrc/src/main/kotlin/BuildVariants.kt b/android/buildSrc/src/main/kotlin/BuildVariants.kt
new file mode 100644
index 0000000000..dcb9e548e2
--- /dev/null
+++ b/android/buildSrc/src/main/kotlin/BuildVariants.kt
@@ -0,0 +1,44 @@
+import BuildTypes.DEBUG
+import BuildTypes.FDROID
+import BuildTypes.LEAK_CANARY
+import BuildTypes.RELEASE
+import Flavors.DEVMOLE
+import Flavors.OSS
+import Flavors.PLAY
+import Flavors.PROD
+
+object BuildTypes {
+ const val DEBUG = "debug"
+ const val RELEASE = "release"
+ const val FDROID = "fdroid"
+ const val LEAK_CANARY = "leakCanary"
+}
+
+object SigningConfigs {
+ const val RELEASE = "release"
+}
+
+object FlavorDimensions {
+ const val BILLING = "billing"
+ const val INFRASTRUCTURE = "infrastructure"
+}
+
+object Flavors {
+ const val OSS = "oss"
+ const val PLAY = "play"
+
+ const val PROD = "prod"
+ const val DEVMOLE = "devmole"
+}
+
+val enabledVariantTriples =
+ listOf(
+ Triple(OSS, PROD, DEBUG),
+ Triple(OSS, PROD, RELEASE),
+ Triple(OSS, PROD, FDROID),
+ Triple(OSS, PROD, LEAK_CANARY),
+ Triple(PLAY, PROD, DEBUG),
+ Triple(PLAY, PROD, RELEASE),
+ Triple(PLAY, DEVMOLE, DEBUG),
+ Triple(PLAY, DEVMOLE, RELEASE)
+ )
diff --git a/android/service/build.gradle.kts b/android/service/build.gradle.kts
index 65d3737068..bbdb862cf3 100644
--- a/android/service/build.gradle.kts
+++ b/android/service/build.gradle.kts
@@ -22,6 +22,13 @@ android {
abortOnError = true
warningsAsErrors = true
}
+
+ flavorDimensions += FlavorDimensions.BILLING
+
+ productFlavors {
+ create(Flavors.OSS) { dimension = FlavorDimensions.BILLING }
+ create(Flavors.PLAY) { dimension = FlavorDimensions.BILLING }
+ }
}
dependencies {
diff --git a/android/test/common/build.gradle.kts b/android/test/common/build.gradle.kts
index 311742c412..99fcb9d2a7 100644
--- a/android/test/common/build.gradle.kts
+++ b/android/test/common/build.gradle.kts
@@ -25,7 +25,9 @@ android {
}
androidComponents {
- beforeVariants { variantBuilder -> variantBuilder.apply { enable = name != "release" } }
+ beforeVariants { variantBuilder ->
+ variantBuilder.apply { enable = name != BuildTypes.RELEASE }
+ }
}
dependencies {
diff --git a/android/test/e2e/build.gradle.kts b/android/test/e2e/build.gradle.kts
index 104f17bceb..8e24974fcd 100644
--- a/android/test/e2e/build.gradle.kts
+++ b/android/test/e2e/build.gradle.kts
@@ -16,6 +16,9 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
targetProjectPath = ":app"
+ missingDimensionStrategy(FlavorDimensions.BILLING, Flavors.OSS)
+ missingDimensionStrategy(FlavorDimensions.INFRASTRUCTURE, Flavors.PROD)
+
fun Properties.addRequiredPropertyAsBuildConfigField(name: String) {
val value = getProperty(name) ?: throw GradleException("Missing property: $name")
buildConfigField(type = "String", name = name, value = "\"$value\"")
@@ -73,7 +76,6 @@ configure<org.owasp.dependencycheck.gradle.extension.DependencyCheckExtension> {
dependencies {
implementation(project(Projects.testCommon))
implementation(project(Dependencies.Mullvad.endpointLib))
-
implementation(Dependencies.AndroidX.testCore)
// Fixes: https://github.com/android/android-test/issues/1589
implementation(Dependencies.AndroidX.testMonitor)
diff --git a/android/test/mockapi/build.gradle.kts b/android/test/mockapi/build.gradle.kts
index dd08cd66a5..8be38fdcbc 100644
--- a/android/test/mockapi/build.gradle.kts
+++ b/android/test/mockapi/build.gradle.kts
@@ -13,6 +13,9 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
targetProjectPath = ":app"
+ missingDimensionStrategy(FlavorDimensions.BILLING, Flavors.OSS)
+ missingDimensionStrategy(FlavorDimensions.INFRASTRUCTURE, Flavors.PROD)
+
testInstrumentationRunnerArguments.putAll(
mapOf(
"clearPackageData" to "true",