diff options
Diffstat (limited to 'android')
| -rw-r--r-- | android/app/build.gradle.kts | 96 | ||||
| -rw-r--r-- | android/buildSrc/src/main/kotlin/BuildVariants.kt | 44 | ||||
| -rw-r--r-- | android/service/build.gradle.kts | 7 | ||||
| -rw-r--r-- | android/test/common/build.gradle.kts | 4 | ||||
| -rw-r--r-- | android/test/e2e/build.gradle.kts | 4 | ||||
| -rw-r--r-- | android/test/mockapi/build.gradle.kts | 3 |
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", |
